Перейти к содержанию
  • записи
    104
  • комментариев
    125
  • просмотра
    15 614

Ветвления кода связанные с адресом


MasterGH

776 просмотров

В этой записи блога не будет чего-то, что показало бы "вау, это что-то новое и есть результат". Все сырое и результат пока мне только снится — быстрый поиск условий и включение, и выключение ветвей по этим условиям. Мыслю я не инструкциями, не группой инструкций, а ветвлениями кода и условиями, которые их запускают. Проще 20 ветвлений по 5 окон, чем тонна инструкций... Жаль пока теория, практики с результатом нет.

 

Рисунок. На нем слева прототип, справа текущий сырой вариант

 

1) ставим брейкпоинт на адрес патронов

2) от него расплетаются ветви кода от каждого хита, от каждой инструкции, и по ретам ветвление выходит из рутины

 

Кружи означают ret-ы. Клик на круг будет переходлм в дизассемблер

Стрелки будут показывать входы и выход связанные с соседними рутинами (поиск общих адресов будет стрелками)

 

58cd27daaaa6c_ret-2.thumb.png.7d05ab961d

 

На экране справа вариант без стрелок, т.к. не успел еще их отладить. 4 ветки трассера по ретам из рутины связанные с адресом патронов, выстрелами.

Потом я продолжал стрелять, перезаряжаться, выкидывать и поднимать оружие. В итоге собрал 20 ветвлений по ретам от инструкций связанные с патронами

 

Скрытый текст

07232118 - 8B 85 90060000  		- mov eax,[ebp+00000690]
0721C03F - 0FB7 8E 90060000  	- movzx ecx,word ptr [esi+00000690]
0722FE69 - 39 86 58030000 		- cmp [esi+00000358],eax
0722FEA8 - 83 BE 58030000 00 	- cmp dword ptr [esi+00000358],00
0721C4A0 - 0FB6 96 B0030000  	- movzx edx,byte ptr [esi+000003B0]
0723155C - 83 BE B0030000 00 	- cmp dword ptr [esi+000003B0],00
07230357 - 83 BE 90060000 00 	- cmp dword ptr [esi+00000690],00
0721E00C - 8B BE 90060000  		- mov edi,[esi+00000690]
0722330C - 01 BE 90060000  		- add [esi+00000690],edi
0722FFC7 - 83 BE 58030000 00 	- cmp dword ptr [esi+00000358],00
072306DF - 83 BE 90060000 00 	- cmp dword ptr [esi+00000690],00
0722E808 - 8B 86 90060000  		- mov eax,[esi+00000690]
07231150 - 8B 8E 90060000  		- mov ecx,[esi+00000690]
07231186 - 83 86 90060000 01	- add dword ptr [esi+00000690],01
072311D4 - 8B 86 90060000 		- mov eax,[esi+00000690]
0723121A - 3B 96 90060000		- cmp edx,[esi+00000690]
07231FE9 - 83 BE 90060000 00	- cmp dword ptr [esi+00000690],00
0721CA71 - 0FB6 86 B0030000		- movzx eax,byte ptr [esi+000003B0]
0721E9B7 - 83 BE 90060000 00	- cmp dword ptr [esi+00000690],00
0721EA26 - DA BE 90060000		- fidivr [esi+00000690]

 

 

58cd2a932e67c_ret-3.thumb.png.3bf787bb73

 

Как видно, довольно все еще сырое, но видно, что все 20 ветвлений по ретам сформировались до корневого цикла.

 

Потом можно будет, я надеюсь, увидеть связи между этим ветвлениями, когда я прикручу стрелки. По кружкам кликать и переходить в дизассемблер и смотреть условия выше. На условии искать другие адреса, которое запускает ветвь кода. На адресах опять делать ветвления (новое окно с ветвлениями о ретам)... На практике будет получаться более двух таких окон (для патронов). Нужно будет искать адреса связанные с условиями в новом окне.

 

Скрытый текст

ClassSettings = {}
ClassSettings.__index = ClassSettings
function ClassSettings:New(_fileName, _maskFile)

	local obj = {}
	obj.stringList = createStringlist()
	obj.fileName = _fileName
	obj.maskFile = _maskFile
	
	obj.directoryPath = getCheatEngineDir()..'autorun'
	obj.filePath = obj.directoryPath..'\\'..obj.fileName
	
	-- Есть ли такой ключ
	function obj:HasKey(keyString)
		local stringCount = self.stringList.Count
		for i=0,stringCount-1 do
			local items = self:Split(self.stringList[i])
			if(keyString == items[1]) then
				return true 
			end
		end
	end
	
	-- Получить значение ключа
	function obj:Get(keyString, defaultValue)
		if(obj:HasKey(keyString)) then
			local stringCount = self.stringList.Count
			for i=0,stringCount-1 do
				local items = self:Split(self.stringList[i])
				if(keyString == items[1]) then
					return  items[2]
				end
			end
		end
		return defaultValue
	end
	
	-- Записать ключ
	function obj:Set(keyString, stringOrDigitalValue)
		-- Искать номер строки
		local stringCount = self.stringList.Count
		for i=0,stringCount-1 do
			local items = self:Split(self.stringList[i])
			if(keyString == items[1]) then
				items[2] = stringOrDigitalValue
				self.stringList.remove(self.stringList[i])
				break
			end
		end
		
		self.stringList.add (keyString..' '..stringOrDigitalValue)
	end
	

	-- Возвращает числовой вариант
	function obj:GetDigital(keyString, defaultValue)
		if(obj:HasKey(keyString)) then
			return tonumber(obj:Get(keyString))
		end
		return defaultValue
	end

	-- Сохранить все ключи
	function obj:Save()
		self.stringList.saveToFile(obj.filePath)
	end

	function obj:FileExist(directoryPath, pathToFile, mask)
		local paths = getFileList(directoryPath, mask, false)
		for i=1,#paths do
			if(paths[i] == pathToFile) then
				return true
			end
		end
		return false
	end
	
	function obj:Split(argString)
		local resultTable = {}
		for i in string.gmatch(argString, "%S+") do
			table.insert(resultTable, i)
		end
		return resultTable
	end

	
	-- Загрузка ключей в память
	if(obj:FileExist(obj.directoryPath, obj.filePath, obj.maskFile)) then
		obj.stringList.loadFromFile(obj.filePath)
	end	
	setmetatable(obj, self)
	return obj
end
	
	
classSettings = ClassSettings:New('userdata2.txt', '*.txt')
----------
function DeleteAllBreakPoints()
	local tableAddressOnBreakPoint = debug_getBreakpointList()
	for i =1, #tableAddressOnBreakPoint do
		debug_removeBreakpoint(tableAddressOnBreakPoint[i])
	end
end


ClassTraceBranch = {}
function ClassTraceBranch:New(_dataAddress, _onEnd)

	local obj  = {}
	obj.address 		= _dataAddress
	obj.OnEnd 			= _onEnd
	obj.Is64Bit 		= targetIs64Bit()
	obj.tableData 		= {}

	--Breakpoint methods: 				bpmInt3=0, bpmDebugRegister=1, bpmException=2
	--breakpoint continue methods:      co_run=0, co_stepinto=1, co_stepover=2
	--Breakpoint triggers:				bptExecute=0, bptAccess=1, bptWrite=2
	--debug_setBreakpoint(self.address, 1, bptExecute, bpmDebugRegister)
	
	
	function obj:OnBreakpoint() 
	
	
		local XIP = 0
		if(self.Is64Bit) then XIP = RIP else XIP = EIP end
		
		local someFind = false
		local endAction = false
		
		for i=1,#self.tableData do
			--if(self.tableData[i].XIP == XIP) then
			if(self.tableData[i].XIP == XIP) then
				self.tableData[i].Count = self.tableData[i].Count + 1
				someFind = true
				if(self.tableData[i].Count > 100) then
					endAction = true
				end
				break
			end
		end
		
		if(endAction) then
			--table.insert ( self.tableData, {XIP = XIP, Count = 1})
			--self:PrintData()
			--print('-->'..string.format('%08X',XIP))
			DeleteAllBreakPoints()
			debug_continueFromBreakpoint(co_run)
			self.OnEnd()
		else
			if(not someFind) then
				local _,opcode,_,_ = splitDisassembledString(disassemble(XIP))
				local isRet = string.match(opcode,'ret')
				--if(isRet) then
				--	print('ret '..string.format('%08X', XIP))
				--end
				table.insert ( self.tableData, {XIP = XIP, Count = 1, isRet = isRet})
				debug_continueFromBreakpoint(co_stepover)
			end
		end
		return 1
	end

	function obj:PrintData()
		local s = ''
		local addressPrevious = getPreviousOpcode(self.address)
		local _,opcode,_,_ = splitDisassembledString(disassemble(addressPrevious))
		print(string.format('%08X - %s:\r\n', addressPrevious, opcode))
		
		for i=1,#self.tableData do
			local _,opcode,_,_ = splitDisassembledString(disassemble(self.tableData[i].XIP))
			s = s..string.format('%08X - %s - %s\r\n', self.tableData[i].XIP, self.tableData[i].Count, opcode)
		end
		print(s)
	end	

	debug_continueFromBreakpoint(co_stepover)
	
	setmetatable (obj, self)
	obj.__index = ClassTraceBranch
	return obj
end

ClassManagerBranches = {}
function ClassManagerBranches:New(mainAddress, sizeBreakPoint)

	local obj  = {}

	
	obj.tableData 				= {} --XIP = 0, traceBranch = nil
	obj.mainAddress				= mainAddress
	obj.sizeBreakPoint 			= sizeBreakPoint
	obj.currentTraceBranch 		= nil
	obj.isLogBranch				= false
	
	local Is64Bit 				= targetIs64Bit()

	function obj:Containts(XIP)
		for i=1, #self.tableData do
			if(self.tableData[i].XIP == XIP) then 
				return true
			end
		end
		return false
	end
	
	function obj:Stop()
		
		DeleteAllBreakPoints()
		
		for i = 1, #self.tableData do
			local addressPrevious = getPreviousOpcode(self.tableData[i].traceBranch.address)
			local _,opcode,_,_ = splitDisassembledString(disassemble(addressPrevious))
			print(string.format('%08X %s', addressPrevious, opcode))
		end
		
		print('\r\n')
		
		for i = 1, #self.tableData do
			self.tableData[i].traceBranch:PrintData()
		end
		
		debug_continueFromBreakpoint(co_run)
	end	
	
	function obj:OnBreakpoint()
	
		if(self.isLogBranch) then
			return self.currentTraceBranch:OnBreakpoint() 
		end

		local XIP = 0
		if(Is64Bit) then XIP = RIP else XIP = EIP end
		
		if(not self:Containts(XIP)) then
	
			local hitAddress = getPreviousOpcode(XIP)
			local _,opcode,_,_ = splitDisassembledString(disassemble(hitAddress))
			--print(string.format('Start Trace at : %08X %s', hitAddress, opcode))
			
			DeleteAllBreakPoints()
			
			self.currentTraceBranch = ClassTraceBranch:New
			(	
				XIP, 
				function ()
					--print('Stop')
					self.isLogBranch = false
					debug_setBreakpoint(self.mainAddress, self.sizeBreakPoint, bptAccess, bpmDebugRegister)
				end
			)

			table.insert (self.tableData, {XIP = XIP, traceBranch = self.currentTraceBranch})
			
			self.isLogBranch = true
		end
		
		return 1
	end
	
	
	print('Start at: '.. obj.mainAddress)
	debug_setBreakpoint(obj.mainAddress, obj.sizeBreakPoint, bptAccess, bpmDebugRegister)
		
	setmetatable (obj, self)
	obj.__index = ClassManagerBranches
	return obj
end


--if(getOpenedProcessID() == 0) then openProcess('test.exe') end

if(getOpenedProcessID() == 0) then 
	openProcess('xrengine.exe')
end

managerBranches = ClassManagerBranches:New('37859970',4)

function debugger_onBreakpoint()
	return managerBranches:OnBreakpoint()
end


--managerBranches:Stop()

-----------------------------

-- КЛАСС ClassMapBranch
ClassMapBranch = {}
ClassMapBranch.__index = ClassMapBranch
function ClassMapBranch:New(_frmMarkers, _managerBranches)

	local _frmMapBranch = createForm(false) --frmDissassembler -- createForm(false)
	
	_frmMapBranch.DoubleBuffered = true
	_frmMapBranch.Caption 	= 'Map branches'
	_frmMapBranch.Width 	= classSettings:GetDigital('obj.frmMapBranch.Width', 500)
	_frmMapBranch.Height 	= classSettings:GetDigital('obj.frmMapBranch.Height', 900)
	_frmMapBranch.Left		= classSettings:GetDigital('obj.frmMapBranch.Left', 0)
	_frmMapBranch.Top 		= classSettings:GetDigital('obj.frmMapBranch.Top', 0)
		

	if(classSettings:Get('obj.frmMapBranch.Visible', '1') == '1') then
		_frmMapBranch.show()
	end
	_frmMapBranch.show()
		
	_frmMapBranch.setBorderStyle(bsSizeable)
	_frmMapBranch.FormStyle = 'fsNormal'
	
	
	local obj = {}
	
	
	obj.classManagerBranches = _managerBranches
	obj.frmMapBranch 		= _frmMapBranch
	obj.frmMarkedBranches	= _frmMarkers
	obj.selectedAddress 	= -1
	obj.mainCanvas 			= obj.frmMapBranch.Canvas
	obj.bufferGraphic 		= createBitmap(obj.frmMapBranch.Canvas.Width, obj.frmMapBranch.Canvas.Height)
	
	obj.dy 					= 20
	obj.column0_X 			= 30	-- маркер X
	obj.column1_X 			= 65
	obj.column2_X 			= 70 + 50
	obj.column3_X 			= 70 + 50 + 40
	obj.extraLineRender_Y	= -20
	obj.tableVisibleAddress = {}		-- содержит данные рисуемой таблицы (см. свойства инже по коду)
	
	-- Можно поставить другие цвета для фона и шрифта
	obj.colorBackground 	=  classSettings:GetDigital('obj.colorBackground', 0x00525252)
	obj.colorFont 			=  0x00FFFFFF --classSettings:GetDigital('obj.colorFont', )
	
	
	obj.frmMapBranch.Color 		= obj.colorBackground
	obj.frmMapBranch.Font.Color = obj.colorFont 
	
	obj.isDirtyData = true
	setProperty(obj.frmMapBranch, 'OnPaint', function () 
		
		if(obj.isDirtyData) then
			obj.isDirtyData = false
			obj:Draw()
		end

		obj.mainCanvas.draw(0, 0, obj.bufferGraphic)
	end)
	
	setProperty(obj.frmMapBranch, 'OnResize', function ()
		if(obj.bufferGraphic.Width ~= obj.mainCanvas.Width or
			obj.bufferGraphic.Height ~= obj.mainCanvas.Height) then
			obj.isDirtyResize = true
		  end
		end
	)

	-- Не уничтожать окно при закрытии
	setProperty(obj.frmMapBranch, 'OnClose', function (sender) 
		return caHide --Possible options: caHide, caFree, caMinimize, caNone
	end
	)		

	
	obj.checkTimer = createTimer(obj.frmMapBranch)
	obj.checkTimer.Interval = 50
	obj.lastTopAddress = 0
	obj.isDirtyResize = false
	obj.needUpdateDraw = false
	
	obj.checkTimer.OnTimer = function ()
	
		obj.needUpdateDraw = true
		if(	obj.needUpdateDraw) then
			obj.needUpdateDraw = false
			obj.frmMapBranch.repaint()
		end

		if(obj.isDirtyResize) then
			obj.isDirtyResize = false
			obj.bufferGraphic.destroy()
			obj.bufferGraphic = createBitmap(obj.frmMapBranch.Canvas.Width, obj.frmMapBranch.Canvas.Height)
			obj.bufferGraphic.Canvas.Brush.Color 	= obj.colorBackground
			obj.bufferGraphic.Canvas.Font.Color 	= obj.colorFont
			obj.bufferGraphic.Canvas.floodFill(x,y)
			obj.isDirtyData = true
			obj.frmMapBranch.repaint()
		end		
	end
	
	
	obj.mainAddress = string.format('%08X',obj.classManagerBranches.mainAddress)
	
	-- Рисует дизассемблерный код и может рисовать пути
	function obj:Draw()
		
		local bufferGraphicCanvas = obj.bufferGraphic.Canvas
		
		bufferGraphicCanvas.Font.Size 		= sizeFont
		bufferGraphicCanvas.Font.Color 		= obj.colorFont
		bufferGraphicCanvas.Pen.Style 		= 'psSolid'
		bufferGraphicCanvas.Brush.Style 	= 'bsClear'
		bufferGraphicCanvas.Brush.Color 	= obj.colorBackground
		
		
		bufferGraphicCanvas.clear()
		obj.frmMapBranch.color = 0xFFFFFFFF -- obj.colorBackground
		bufferGraphicCanvas.Brush.Color = 0xFFFFFFFF
		bufferGraphicCanvas.Pen.Style   = 0xFFFFFFFF
		
		--bufferGraphicCanvas.Brush.Style = 'bsClear'
		
		local mainPoint = 
		{
			x = obj.frmMapBranch.Width / 2,
			y =  obj.frmMapBranch.Height  - 50
		}
		
		bufferGraphicCanvas.textOut(mainPoint.x, mainPoint.y, obj.mainAddress)
		bufferGraphicCanvas.line(mainPoint.x - 300, mainPoint.y - 30, mainPoint.x + 300, mainPoint.y - 30)
		
		local tableData = obj.classManagerBranches.tableData
		for i = 1, #tableData do
			--local addressPrevious = getPreviousOpcode(tableData[i].traceBranch.address)
			--local _,opcode,_,_ = splitDisassembledString(disassemble(addressPrevious))
			--local s = string.format('%08X %s', addressPrevious, opcode)
			--bufferGraphicCanvas.textOut(100, 100 + i * 20, 'Test: '.. s)
			local dx = i*40
			local dy = 20
			
			--bufferGraphicCanvas.line
			--(
			--	mainPoint.x - 300 + dx,
			--	mainPoint.y - 30 - dy,
			--	mainPoint.x - 300 + dx,
			--	mainPoint.y - 30
			--)
			
			local tableDataFromBranche = tableData[i].traceBranch.tableData
			local countRets = 0
			for j = 1, #tableDataFromBranche do
				--table.insert ( self.tableData, {XIP = XIP, Count = 1, isRet = string.match(opcode,'ret')})
				--table.insert ( self.tableData, {XIP = XIP, Count = 1, isRet = string.match(opcode,'ret')})
				if(tableDataFromBranche[j].isRet) then
					countRets = countRets + 1
					bufferGraphicCanvas.ellipse
					(	
						mainPoint.x - 300 + dx - 5,
						mainPoint.y - 30 - dy - countRets * 20 - 5,
						mainPoint.x - 300 + dx + 6,
						mainPoint.y - 30 - dy - countRets * 20 + 6
					)
				end
			end
			
			bufferGraphicCanvas.line
			(
				mainPoint.x - 300 + dx,
				mainPoint.y,
				mainPoint.x - 300 + dx,
				mainPoint.y - dy - countRets * 20 - 10
			)
		end	
		
		--local priority1 = math.random(0,155)
		--local someColor = byteTableToDword({priority1,priority1,priority1,0})
		--bufferGraphicCanvas.Font.Color = someColor
				

			

		obj.mainCanvas.draw(0, 0, obj.bufferGraphic)
	end	
	

	function obj:DrawArrow(point1, point2, distance, colorArrow, minY, a1_IsFarTop, a1_IsFarBottom, a2_IsFarTop, a2_IsFarBottom, a1_IsFarTop, a1_IsFarBottom, a2_IsFarTop, a2_IsFarBottom)

		local bufferCanvas = obj.bufferGraphic.Canvas
		
		bufferCanvas.Pen.Color = colorArrow
		bufferCanvas.Pen.Style = 'psDot'	
		
		local height = bufferCanvas.Height
		
		isDrawSideLine1 = true
		if(point1.y < minY) 			then	point1.y = minY  isDrawSideLine1 = false
		elseif (point1.y > height) 	then	point1.y = height isDrawSideLine1 = false
		end
		
		isDrawRow = true
		if(point2.y < minY) 			then	point2.y = minY	  isDrawRow = false
		elseif (point2.y > height) 	then	point2.y = height isDrawRow = false
		end
		
		if(isDrawSideLine1) then
			bufferCanvas.line(point1.x, point1.y, point2.x - distance, point1.y)
		end
		bufferCanvas.line(point2.x - distance, point1.y, point2.x - distance, point2.y)
		

	
		if(isDrawRow) then
			bufferCanvas.line(point1.x, point2.y, point2.x - distance, point2.y)
			obj.bufferGraphic.Canvas.Pen.Style = 'psSolid' --'psSolid'
			local x1 = point2.x - 5
			local x2 = point2.x 
			local y2 = point2.y
			
			-- Рисование стрелки костыльным способом
			bufferCanvas.line(x1,		y2 - 3,			x2,		y2)
			bufferCanvas.line(x1,		y2 - 7 + 10,	x2,		y2)
			bufferCanvas.line(x1,		y2 - 3,			x1,		y2 - 7 + 10)
			bufferCanvas.line(x1 + 1,	y2 - 2,			x1 + 1, y2 - 7 + 9)
			bufferCanvas.line(x1 + 2,	y2 - 1,			x1 + 2, y2 - 7 + 9)
			bufferCanvas.line(x1,		y2 - 1,			x1 + 6, y2)
		end

	end
				
		
	obj.frmMapBranch.OnDestroy = function (sender)
		obj:SaveParameters()
	end
	
	function obj:SaveParameters()
	
		classSettings:Set('obj.frmMapBranch.Width', obj.frmMapBranch.Width)
		classSettings:Set('obj.frmMapBranch.Height', obj.frmMapBranch.Height)
		classSettings:Set('obj.frmMapBranch.Left', obj.frmMapBranch.Left)
		classSettings:Set('obj.frmMapBranch.Top', obj.frmMapBranch.Top)
		
		classSettings:Set('obj.colorBackground', obj.colorBackground)
		
		if(obj.frmMapBranch.Visible) then
			classSettings:Set('obj.frmMapBranch.Visible', '1')
		else
			classSettings:Set('obj.frmMapBranch.Visible', '0')
		end
			
		classSettings:Save()
	end			
		
	obj:Draw()

	setmetatable(obj, self)
	return obj
end	



mapBranch = ClassMapBranch:New(frmMarkedBranches, managerBranches)

 

 

0 Комментариев


Рекомендуемые комментарии

Комментариев нет

Пожалуйста, войдите, чтобы комментировать

Вы сможете оставить комментарий после входа в



Войти
×
×
  • Создать...

Важная информация

Находясь на нашем сайте, Вы автоматически соглашаетесь соблюдать наши Условия использования.