|
Cheat Engine The Official Site of Cheat Engine
|
View previous topic :: View next topic |
Author |
Message |
GH*master Expert Cheater Reputation: 8
Joined: 10 Jan 2008 Posts: 159
|
Posted: Sun Apr 30, 2017 2:34 am Post subject: Possiible access to DR6 register? |
|
|
We have registers DR0, DR1, DR2, DR3 contain linear addresses of four hardware breakpoints. One or more registers are used
I need to know what hardware breakpoints was executed at moment time.
The DR6 debug state register contains information about which of the breakpoints caused a particular debugging situation, and some other information.
Access to DR6 register possiible from Lua engine? Other solutions?
Thanks!
Code: | --[[
Версия: 0.01.b1
Выход из рутины до близжайшего цикла
]]--
mainAddress = 0x4DA9FEF0 -- 025B3818 -- адрес некоторого параметра в игре 0045B5A4
nextAddress = nil
is64bits = targetIs64Bit()
tableInstruction ={}
tableBreakpointsAddress ={}
-- Есть ли такой брейкпоинт в истории
function ContaintsBeakPoint(address)
for i = 1, #tableBreakpointsAddress do
if tableBreakpointsAddress[i] == address then
return true
end
end
return false
end
-- Возвращает адрес по ret
function GetNextAddressFromRET(address)
if is64bits then
nextAddress = readPointer(RSP)
else
nextAddress = readPointer(ESP)
end
return nextAddress
end
-- Возвращает адрес по Jmp
function GetNextAddressFromJMP(address)
local disassembledstring = nil
if is64bits then
disassembledstring = disassemble(RIP)
else
disassembledstring = disassemble(EIP)
end
local _, opcode, _, _ = splitDisassembledString(disassembledstring)
return GetAddressFromOpcode(opcode)
end
-- Перевод числа в битовую таблицу
function ToBits(num, bits)
local t = {}
for b = bits, 1, -1 do
rest = math.fmod(num,2)
t[b] = math.floor(rest)
num = (num-rest)/2
end
if num == 0 then return t else return {'Not enough bits to represent this number'} end
end
-- Возвращает таблицу флагов
function GetEFLAGS()
local bitsTable = ToBits(EFLAGS, 16)
local tableEFLAGS =
{
OF = bitsTable[17-12],
DF = bitsTable[17-11],
SF = bitsTable[17-8],
ZF = bitsTable[17-7],
AF = bitsTable[17-5],
PF = bitsTable[17-3],
CF = bitsTable[17-1]
}
return tableEFLAGS
end
-- Возвращает адрес из опкода jmp dword ptr [edi*4+07895D88] или jmp 07895D88
function GetAddressFromOpcode (opcode)
local rightLine = string.match(opcode, '%S*%s*(%S*)')
local isPointer = string.match(opcode, '%[')
if isPointer then
rightLine = string.match(opcode, '%[(.*)%]')
--00454664 - 8B 83 60030000 - mov eax,[ebx+00000360]
if string.match(opcode, 'eax') then rightLine = string.gsub(rightLine, 'eax', string.format('%X', EAX)) end
if string.match(opcode, 'ebx') then rightLine = string.gsub(rightLine, 'ebx', string.format('%X', EBX)) end
if string.match(opcode, 'ecx') then rightLine = string.gsub(rightLine, 'ecx', string.format('%X', ECX)) end
if string.match(opcode, 'edx') then rightLine = string.gsub(rightLine, 'edx', string.format('%X', EDX)) end
if string.match(opcode, 'esi') then rightLine = string.gsub(rightLine, 'esi', string.format('%X', ESI)) end
if string.match(opcode, 'edi') then rightLine = string.gsub(rightLine, 'edi', string.format('%X', EDI)) end
if string.match(opcode, 'esp') then rightLine = string.gsub(rightLine, 'esp', string.format('%X', ESP)) end
if string.match(opcode, 'ebp') then rightLine = string.gsub(rightLine, 'ebp', string.format('%X', EBP)) end
if is64bits then
if string.match(opcode, 'rax') then rightLine = string.gsub(rightLine, 'rax', string.format('%X', RAX)) end
if string.match(opcode, 'rbx') then rightLine = string.gsub(rightLine, 'rbx', string.format('%X', RBX)) end
if string.match(opcode, 'rcx') then rightLine = string.gsub(rightLine, 'rcx', string.format('%X', RCXX)) end
if string.match(opcode, 'rdx') then rightLine = string.gsub(rightLine, 'rdx', string.format('%X', RDX)) end
if string.match(opcode, 'rsi') then rightLine = string.gsub(rightLine, 'rsi', string.format('%X', RSI)) end
if string.match(opcode, 'rdi') then rightLine = string.gsub(rightLine, 'rdi', string.format('%X', RDI)) end
if string.match(opcode, 'rsp') then rightLine = string.gsub(rightLine, 'rsp', string.format('%X', RSP)) end
if string.match(opcode, 'rbp') then rightLine = string.gsub(rightLine, 'rbp', string.format('%X', RBP)) end
if string.match(opcode, 'r8') then rightLine = string.gsub(rightLine, 'r8', string.format('%X', R8)) end
if string.match(opcode, 'r9') then rightLine = string.gsub(rightLine, 'r9', string.format('%X', R9)) end
if string.match(opcode, 'r10') then rightLine = string.gsub(rightLine, 'r10', string.format('%X', R10)) end
if string.match(opcode, 'r11') then rightLine = string.gsub(rightLine, 'r11', string.format('%X', R11)) end
if string.match(opcode, 'r12') then rightLine = string.gsub(rightLine, 'r12', string.format('%X', R12)) end
if string.match(opcode, 'r13') then rightLine = string.gsub(rightLine, 'r13', string.format('%X', R13)) end
if string.match(opcode, 'r14') then rightLine = string.gsub(rightLine, 'r14', string.format('%X', R14)) end
if string.match(opcode, 'r15') then rightLine = string.gsub(rightLine, 'r15', string.format('%X', R15)) end
end
return getAddress('['..rightLine..']')
else
if string.match(opcode, 'eax') then rightLine = string.gsub(rightLine, 'eax', string.format('%X', EAX)) end
if string.match(opcode, 'ebx') then rightLine = string.gsub(rightLine, 'ebx', string.format('%X', EBX)) end
if string.match(opcode, 'ecx') then rightLine = string.gsub(rightLine, 'ecx', string.format('%X', ECX)) end
if string.match(opcode, 'edx') then rightLine = string.gsub(rightLine, 'edx', string.format('%X', EDX)) end
if string.match(opcode, 'esi') then rightLine = string.gsub(rightLine, 'esi', string.format('%X', ESI)) end
if string.match(opcode, 'edi') then rightLine = string.gsub(rightLine, 'edi', string.format('%X', EDI)) end
if string.match(opcode, 'esp') then rightLine = string.gsub(rightLine, 'esp', string.format('%X', ESP)) end
if string.match(opcode, 'ebp') then rightLine = string.gsub(rightLine, 'ebp', string.format('%X', EBP)) end
if is64bits then
if string.match(opcode, 'rax') then rightLine = string.gsub(rightLine, 'rax', string.format('%X', RAX)) end
if string.match(opcode, 'rbx') then rightLine = string.gsub(rightLine, 'rbx', string.format('%X', RBX)) end
if string.match(opcode, 'rcx') then rightLine = string.gsub(rightLine, 'rcx', string.format('%X', RCXX)) end
if string.match(opcode, 'rdx') then rightLine = string.gsub(rightLine, 'rdx', string.format('%X', RDX)) end
if string.match(opcode, 'rsi') then rightLine = string.gsub(rightLine, 'rsi', string.format('%X', RSI)) end
if string.match(opcode, 'rdi') then rightLine = string.gsub(rightLine, 'rdi', string.format('%X', RDI)) end
if string.match(opcode, 'rsp') then rightLine = string.gsub(rightLine, 'rsp', string.format('%X', RSP)) end
if string.match(opcode, 'rbp') then rightLine = string.gsub(rightLine, 'rbp', string.format('%X', RBP)) end
if string.match(opcode, 'r8') then rightLine = string.gsub(rightLine, 'r8', string.format('%X', R8)) end
if string.match(opcode, 'r9') then rightLine = string.gsub(rightLine, 'r9', string.format('%X', R9)) end
if string.match(opcode, 'r10') then rightLine = string.gsub(rightLine, 'r10', string.format('%X', R10)) end
if string.match(opcode, 'r11') then rightLine = string.gsub(rightLine, 'r11', string.format('%X', R11)) end
if string.match(opcode, 'r12') then rightLine = string.gsub(rightLine, 'r12', string.format('%X', R12)) end
if string.match(opcode, 'r13') then rightLine = string.gsub(rightLine, 'r13', string.format('%X', R13)) end
if string.match(opcode, 'r14') then rightLine = string.gsub(rightLine, 'r14', string.format('%X', R14)) end
if string.match(opcode, 'r15') then rightLine = string.gsub(rightLine, 'r15', string.format('%X', R15)) end
end
end
return getAddress(rightLine)
end
-- Возвращает адрес по Jmp condition, когда тот выполняется или не выполняется
function GetNextAddressFromConditionJMP(address, size)
local _,opcode,_,_ = splitDisassembledString(disassemble(address))
local leftString = string.match(opcode, '%S*')
local eflags = GetEFLAGS()
if (leftString == 'jnz' or leftString == 'jne') then
if eflags.ZF == 0 then
return GetAddressFromOpcode(opcode)
end
elseif (leftString == 'je' or leftString == 'jz') then
if eflags.ZF == 1 then
return GetAddressFromOpcode(opcode)
end
elseif (leftString == 'jg' or leftString == 'jnle') then
if eflags.ZF == 0 and eflags.SF == eflags.OF then
return GetAddressFromOpcode(opcode)
end
elseif (leftString == 'jb' or leftString == 'jc' or leftString == 'jnae') then
if eflags.CF == 1 then
return GetAddressFromOpcode(opcode)
end
elseif (leftString == 'jae') then
if eflags.CF == 0 then
return GetAddressFromOpcode(opcode)
end
elseif (leftString == 'ja') then
if eflags.CF == 0 and eflags.ZF == 0 then
return GetAddressFromOpcode(opcode)
end
elseif (leftString == 'jbe') then
if eflags.CF == 1 and eflags.ZF == 1 then
return GetAddressFromOpcode(opcode)
end
elseif (leftString == 'jl' or leftString == 'jnge') then
if eflags.SF ~= eflags.OF then
return GetAddressFromOpcode(opcode)
end
elseif (leftString == 'jle' or leftString == 'jng') then
if eflags.ZF == 1 or eflags.SF ~= eflags.OF then
return GetAddressFromOpcode(opcode)
end
elseif (leftString == 'jna') then
if eflags.CF == 1 or eflags.ZF == 1
then return GetAddressFromOpcode(opcode)
end
elseif (leftString == 'jc') then
if eflags.CF == 1 then
return GetAddressFromOpcode(opcode)
end
elseif (leftString == 'jp' or leftString == 'jpe') then
if eflags.PF == 1 then
return GetAddressFromOpcode(opcode)
end
elseif (leftString == 'jnp' or leftString == 'jpo')then
if eflags.PF == 0 then
return GetAddressFromOpcode(opcode)
end
elseif (leftString == 'jnb' or leftString == 'jnc') then
if eflags.CF == 0 then
return GetAddressFromOpcode(opcode)
end
elseif (leftString == 'jnbe') then
if eflags.CF == 0 and eflags.ZF == 0 then
return GetAddressFromOpcode(opcode)
end
elseif (leftString == 'jno') then
if eflags.OF == 0 then
return GetAddressFromOpcode(opcode)
end
elseif (leftString == 'jns') then
if eflags.SF == 0 then
return GetAddressFromOpcode(opcode)
end
elseif (leftString == 'jo') then
if eflags.OF == 1 then
return GetAddressFromOpcode(opcode)
end
elseif (leftString == 'js') then
if eflags.SF == 1 then
return GetAddressFromOpcode(opcode)
end
elseif (leftString == 'jge' or leftString == 'jnl') then
if eflags.CF == 1 and eflags.OF == 1 then
return GetAddressFromOpcode(opcode)
end
elseif (leftString == 'jrcxz') then
if RCX == 0 then
return GetAddressFromOpcode(opcode)
end
elseif (leftString == 'jecxz') then
if ECX == 0 then
return GetAddressFromOpcode(opcode)
end
end
return address + size
end
-- Это ret инструкция?
function IsRet(address)
local value = readBytes(address,1, false)
return value == 0xC3 or value == 0xCB or value == 0xC2 or value == 0xCA
end
-- -- Это call инструкция?
-- function IsCall(address)
-- local value = readBytes(address,1, false)
-- return value == 0xFF or value == 0xE8 -- or value == 0x9A
-- end
-- Это jmp инструкция?
function IsJMP(address)
local value = readBytes (address, 1, false)
-- Исключенеие не подходщих инструкций по первому байту FF и следующему за ним
if value == 0xFF then
local nextByte = readBytes (address + 1, 1, false)
if nextByte == 0x05 or nextByte == 0x15 or
nextByte == 0x50 or nextByte == 0x70 or
nextByte == 0x30 or nextByte == 0x75 then
return false
end
end
--[[
078921A8 - EB 38 - jmp 078921E2
0789242D - E9 E2000000 - jmp 07892514
07894F4C - FF E2 - jmp edx
07895C67 - FF 24 BD 885D8907 - jmp dword ptr [edi*4+07895D88]
]]--
return value == 0xEB or value == 0xE9 or value == 0xFF -- or value == 0xEA
end
-- Это jmp condition инструкция?
function IsConditionJMP(address)
local value = readBytes (address, 1, false)
return
value == 0x77 or value == 0x73 or value == 0x72 or value == 0x76 or
value == 0xE3 or value == 0x74 or value == 0x7F or value == 0x7D or
value == 0x7C or value == 0x7E or value == 0x75 or value == 0x71 or
value == 0x7B or value == 0x79 or value == 0x70 or value == 0x7A or
value == 0x78 or value == 0x0F
end
-- Возвращает адрес на который, будет переход
function GetNextAddress(addressXIP)
-- Определить на какой инструкции мы находимся, чтобы узнать на какую следующу инструкцию ставить бряк
-- ret - прыжок по смещению ESP/RSP
-- jmp - прыжок без условия
-- je, jne, jxx - прыжок с улосвием
-- Определить размер инструкции, тип инструкции на текущем addressXIP
local findIndex = -1
for i = 1, #tableInstruction do
if tableInstruction[i].XIP == addressXIP then
findIndex = i
break
end
end
local size = 0
local isRet = false
local isJMP = false
local isCJMP = false
if findIndex == -1 then
-- Если нет данных
---------------- ЗАПОМИНАТЬ РАЗМЕР ИНСТРУКЦИИ (чтобы не дизассемблировать повторно)
size = getInstructionSize(addressXIP)
isRet = IsRet(addressXIP)
isJMP = IsJMP(addressXIP)
isCJMP = IsConditionJMP(addressXIP)
table.insert(tableInstruction, {XIP = addressXIP, SIZE = size, ISRET = isRet, ISJMP = isJMP, ISCJMP = isCJMP})
else
-- Если данные есть
size = tableInstruction[findIndex].SIZE
isRet = tableInstruction[findIndex].ISRET
isJMP = tableInstruction[findIndex].ISJMP
isCJMP = tableInstruction[findIndex].ISCJMP
end
---------------
if isRet then
local storyAddress = nextAddress
nextAddress = GetNextAddressFromRET(addressXIP)
print('> RET :' ..disassemble(storyAddress)..AddSpace(' -->> :' ..disassemble(nextAddress)))
elseif isJMP then
--local storyAddress = nextAddress
nextAddress = GetNextAddressFromJMP(addressXIP)
--print('> isJMP :' ..disassemble(storyAddress)..AddSpace(' -->> :' ..disassemble(nextAddress)))
elseif isCJMP then
--local storyAddress = nextAddress
nextAddress = GetNextAddressFromConditionJMP(addressXIP, size)
--print('> isCJMP :' ..disassemble(storyAddress)..AddSpace(' -->> :' ..disassemble(nextAddress)))
else
nextAddress = addressXIP + size
end
return nextAddress
end
function AddSpace(line)
return line..string.rep (' ', 80 - string.len(line))
end
function debugger_onBreakpoint()
local isContaintsBreakPoint = false
-- Удалить прошлый брейкпоинт
if(nextAddress ~= nil) then
isContaintsBreakPoint = ContaintsBeakPoint(nextAddress)
if isContaintsBreakPoint then
debug_removeBreakpoint(nextAddress)
end
end
-- Поставить брейкпоинт на следующую инструкцию не входя в call-ы
local XIP = 0
if is64bits then XIP = EIP else XIP = RIP end
nextAddress = GetNextAddress(XIP)
-- Нельзя ставить брейкпоинт на адресс повторно
if not ContaintsBeakPoint(nextAddress) then
debug_setBreakpoint(nextAddress, 1, bptExecute, bpmDebugRegister)
table.insert(tableBreakpointsAddress, nextAddress)
end
return 1 --1 не показывать дизассемблер
end
if getOpenedProcessID() == 0 then
--openProcess('DebugStep.exe')
openProcess('xrEngine.exe')
end
--bptWrite
--bptAccess
--debug_removeBreakpoint()
debug_setBreakpoint(mainAddress, 4, bptAccess, bpmDebugRegister) |
|
|
Back to top |
|
|
Dark Byte Site Admin Reputation: 458
Joined: 09 May 2003 Posts: 25296 Location: The netherlands
|
Posted: Sun Apr 30, 2017 4:19 am Post subject: |
|
|
instead of using function debugger_onBreakpoint() you can also use
debug_setBreakpoint(mainAddress, 4, bptAccess, bpmDebugRegister, functiontocallonbp)
that will be unique for that specific breakpoint
_________________
Do not ask me about online cheats. I don't know any and wont help finding them.
Like my help? Join me on Patreon so i can keep helping |
|
Back to top |
|
|
GH*master Expert Cheater Reputation: 8
Joined: 10 Jan 2008 Posts: 159
|
Posted: Sun Apr 30, 2017 4:55 am Post subject: |
|
|
Oh sure. I forgot about this functiontocall
Quote: | debug_setBreakpoint(address, size OPTIONAL, trigger OPTIONAL, breakpointmethod OPTIONAL, functiontocall() OPTIONAL) : sets a breakpoint of a specific size at the given address. if trigger is bptExecute then size is ignored. If trigger is ignored then it will be of type bptExecute, which obviously also ignores the size then as well
|
Thanks, I'll try this function
|
|
Back to top |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You can download files in this forum
|
|