SetBatchLines, -1
ProcessName := "test.exe"
Start := 0, End := 0x800000000000 ; Диапазон адресов.
cAddrs := 1 ; Сколько адресов искать.
Number := 0x084F8D08478B1574 ; Искомое число.
cbTarget := 8 ; Длина искомого в байтах.
VarSetCapacity(Target, cbTarget)
NumPut(Number, Target, 0, "uint64")
; Поиск. Функция вернёт массив адресов либо 0, если ничего не найдено.
Found := SearchProcess(ProcessName, Start, End, &Target, cbTarget, cAddrs)
Time := (A_TickCount - StartTime) / 1000
If (Found = 0) {
MsgBox, Ничего не найдено
ExitApp
}
Else {
MsgBox, % "Найден адрес: 0x" Format("{1:X}", Found[1])
}
; ============================== Функция =======================================
SearchProcess(NameOrPID, StartAddr, EndAddr, pTarget, cbTarget = 4, cAddrs = 100)
{
static Code := 0, MFunc, Len, Page := 0x1000, mbi, mbiSize
static stateOffset, protOffset, regSizeOffset
static Rights := 0x410 ; PROCESS_VM_READ | PROCESS_QUERY_INFORMATION
static MEM_COMMIT := 0x1000, PAGE_READWRITE := 4, PAGE_READONLY := 2
static PAGE_WRITECOPY := 0x08
static BufSize := 0x100000 ; 1 MB. Размер буфера для чтения из процесса.
If (Code != 0) ; Если не первый вызов, то машинный код уже готов.
GoTo Process
If (A_PtrSize = 8) { ; x64
mbiSize := 48, stateOffset := 32, protOffset := 36, regSizeOffset := 24
Code =
( Join LTrim
48894C240848895424104C894424184C894C2420555357564889E54883EC08488B
7D288B4D308B5540488B5D48C745F800000000FFCA29D1783B488B7538ACF2AE75
325189D1F3A60F94C04829D14801CF5984C0741B488D47FF482B45284803455848
89034883C308FF45F8FF4D50740485C975C58B45F8488D65005E5F5B5DC3
)
}
Else { ; x86
mbiSize := 28, stateOffset := 16, protOffset := 20, regSizeOffset := 12
Code =
( Join LTrim
5553575689E583EC048B7D148B4D188B55208B5D24C745FC000000004A29D17833
8B751CACF2AE752B5189D1F3A60F94C029D101CF5984C074168D47FF2B45140345
2C890383C304FF45FCFF4D28740485C975CD8B45FC89EC5E5F5B5DC21C00
)
}
Len := StrLen(Code) // 2
; Память под машинный код.
MFunc := DllCall("VirtualAlloc", "ptr", 0, "ptr", Len
, "uint", 0x3000, "uint", 0x40, "ptr")
Loop, % Len
NumPut("0x" . SubStr(Code, A_Index * 2 - 1, 2), MFunc + 0
, A_Index - 1, "uchar")
VarSetCapacity(mbi, mbiSize) ; Структура MEMORY_BASIC_INFORMATION
Process:
Process, Exist, %NameOrPID%
If !(PID := ErrorLevel) {
MsgBox, Процесс не найден
Return 0
}
hProcess := DllCall("OpenProcess", "uint", Rights, "int", False, "uint", PID, "ptr")
If(!hProcess) {
MsgBox, Не удалось открыть процесс.
Return 0
}
VarSetCapacity(AddrBuf, A_PtrSize * cAddrs, 0) ; Буфер для найденных адресов.
VarSetCapacity(Buf, BufSize) ; Буфер для считанной из процесса памяти.
CurAddr := (StartAddr // Page) * Page ; Текущий адрес. Округлить до начала страницы.
pAddrBuf := &AddrBuf ; Указатель на свободное место в буфере адресов.
FoundAll := 0 ; Всего найдено.
While(CurAddr < EndAddr) {
BytesRet := DllCall("VirtualQueryEx", "ptr", hProcess, "ptr", CurAddr
, "ptr", &mbi, "uint", mbiSize, "ptr")
If (BytesRet = 0) {
Break
}
RegionSize := NumGet(mbi, regSizeOffset, "uptr")
; Если память не выделена (адреса свободны или только зарезервированы),
; пропускаем весь этот регион.
If (NumGet(mbi, stateOffset, "uint") != MEM_COMMIT) {
CurAddr += RegionSize
If (A_PtrSize = 4 && CurAddr > 0xFFFFFFFF)
GoTo Done
Continue
}
Protect := NumGet(mbi, protOffset, "uint")
; Проверять только память для записи и чтения (данные).
If !(Protect = PAGE_READWRITE || Protect = PAGE_WRITECOPY
|| Protect = PAGE_READONLY) {
CurAddr += RegionSize
If (A_PtrSize = 4 && CurAddr > 0xFFFFFFFF)
GoTo Done
Continue
}
While(RegionSize) { ; Считывание в буфер и поиск в нём.
ReadSize := BufSize < RegionSize ? BufSize : RegionSize
RegionSize -= ReadSize
Ret := DllCall("ReadProcessMemory", "ptr", hProcess, "ptr", CurAddr
, "ptr", &Buf, "ptr", ReadSize
, "ptr *", BytesRead, "int")
If (!Ret) { ; Если ошибка чтения, идём дальше.
CurAddr += ReadSize
Continue
}
; Вызов машинной функции для поиска.
Found := DllCall(MFunc, "ptr", &Buf, "ptr", BytesRead
, "ptr", pTarget, "uint", cbTarget
, "ptr", pAddrBuf, "uint", cAddrs - FoundAll
, "ptr", CurAddr, "uint")
CurAddr += ReadSize
If (Found = 0) {
Continue
}
If ((FoundAll += Found) < cAddrs) {
pAddrBuf += Found * A_PtrSize
Continue
}
Goto Done
}
}
Done:
DllCall("CloseHandle", "ptr", hProcess)
If (FoundAll = 0)
Return 0
Array := []
Loop, %FoundAll%
Array.Insert(NumGet(&AddrBuf+(A_PtrSize * (A_Index - 1)), 0, "uptr"))
Return Array
}