<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Ветвления кода связанные с адресом (старые записи)]]></title><description><![CDATA[<p dir="auto">В этой записи блога не будет чего-то, что показало бы "вау, это что-то новое и есть результат". Все сырое и результат пока мне только снится — быстрый поиск условий и включение, и выключение ветвей по этим условиям. Мыслю я не инструкциями, не группой инструкций, а ветвлениями кода и условиями, которые их запускают. Проще 20 ветвлений по 5 окон, чем тонна инструкций... Жаль пока теория, практики с результатом нет.</p>
<p dir="auto">Рисунок. На нем слева прототип, справа текущий сырой вариант</p>
<ol>
<li>
<p dir="auto">ставим брейкпоинт на адрес патронов</p>
</li>
<li>
<p dir="auto">от него расплетаются ветви кода от каждого хита, от каждой инструкции, и по ретам ветвление выходит из рутины</p>
</li>
</ol>
<p dir="auto">Кружи означают ret-ы. Клик на круг будет переходлм в дизассемблер</p>
<p dir="auto">Стрелки будут показывать входы и выход связанные с соседними рутинами (поиск общих адресов будет стрелками)</p>
<p dir="auto"><img src="/assets/uploads/files/1684618036215-e3ab56bb-c1a6-4626-bead-f41fbb327a0d-image.png" alt="e3ab56bb-c1a6-4626-bead-f41fbb327a0d-image.png" class=" img-fluid img-markdown" /><br />
На экране справа вариант без стрелок, т.к. не успел еще их отладить. 4 ветки трассера по ретам из рутины связанные с адресом патронов, выстрелами.</p>
<p dir="auto">Потом я продолжал стрелять, перезаряжаться, выкидывать и поднимать оружие. В итоге собрал 20 ветвлений по ретам от инструкций связанные с патронами</p>
<pre><code>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]
</code></pre>
<p dir="auto"><img src="/assets/uploads/files/1684618064172-a80c8713-7d3b-48ee-9fd4-bb2ed6058b0c-image.png" alt="a80c8713-7d3b-48ee-9fd4-bb2ed6058b0c-image.png" class=" img-fluid img-markdown" /></p>
<p dir="auto">Как видно, довольно все еще сырое, но видно, что все 20 ветвлений по ретам сформировались до корневого цикла.</p>
<p dir="auto">Потом можно будет, я надеюсь, увидеть связи между этим ветвлениями, когда я прикручу стрелки. По кружкам кликать и переходить в дизассемблер и смотреть условия выше. На условии искать другие адреса, которое запускает ветвь кода. На адресах опять делать ветвления (новое окно с ветвлениями о ретам)... На практике будет получаться более двух таких окон (для патронов). Нужно будет искать адреса связанные с условиями в новом окне.</p>
<pre><code>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 &gt; 100) then
					endAction = true
				end
				break
			end
		end
		
		if(endAction) then
			--table.insert ( self.tableData, {XIP = XIP, Count = 1})
			--self:PrintData()
			--print('--&gt;'..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 &lt; minY) 			then	point1.y = minY  isDrawSideLine1 = false
		elseif (point1.y &gt; height) 	then	point1.y = height isDrawSideLine1 = false
		end
		
		isDrawRow = true
		if(point2.y &lt; minY) 			then	point2.y = minY	  isDrawRow = false
		elseif (point2.y &gt; 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)
</code></pre>
]]></description><link>https://celua.ru/topic/113/ветвления-кода-связанные-с-адресом-старые-записи</link><generator>RSS for Node</generator><lastBuildDate>Wed, 20 May 2026 04:04:22 GMT</lastBuildDate><atom:link href="https://celua.ru/topic/113.rss" rel="self" type="application/rss+xml"/><pubDate>Sat, 20 May 2023 21:33:44 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Ветвления кода связанные с адресом (старые записи) on Sat, 20 May 2023 21:33:49 GMT]]></title><description><![CDATA[<h1>Трассеровка по ретам</h1>
<p dir="auto">-------<br />
<img src="/assets/uploads/files/1684618172739-857b57ff-3395-4d71-9f76-e191f66fc90b-image.png" alt="857b57ff-3395-4d71-9f76-e191f66fc90b-image.png" class=" img-fluid img-markdown" /></p>
<p dir="auto">На скриншоте 22 ветви трассеровки от адреса патронов не входя в call-ы до корневого цикла. Корневой цикл определяется, когда поиск происходит более трех секунд и не находит ничего. Вполне хватает этого времени. Буду еще повторно тестить и проверять доходит ли он цикла или надо еще что-то придумывать.</p>
<p dir="auto">Желтым выделяется точка, вертикальная полоса ветви и связи с такими же узлами. Узел это адрес выхода из ret</p>
<p dir="auto">Внизу ряд счетчиков от 00 до 99. Если более 99 то отсчет заного. Показывает дианамику обращения к ветвям после нахождения корневого цикла</p>
<p dir="auto">Есть еще несколько функций, которых не видно на скриншоте — в контекстном меню.</p>
<p dir="auto">Анализ можно запустить из окна CE из главной таблицы, выделив адрес и опцию либо на чтение, либо на доступ.</p>
<p dir="auto">При тестах увидел, что логи неполные. Например, первый кружок это инструкция читающая патроны очень часто. От этой инструкции идут вверх множество вариантов ветвей,а  у меня один вариант — вертикальная полоска с кружками. От первого круга надо сделать ветвление влево и вправо.</p>
<p dir="auto">Занялся модернизацией этого рисования и оптимизацией. Например, чтобы определить является ли проход по ret, то не нужен дизассемблер. Залез в доки и посмотрел опкоды</p>
<pre><code>function IsRet(address)
		local value = readBytes(address,1, false)
		return value == 0xC3 or value == 0xCB or  value == 0xC2 or value == 0xCA
	end
</code></pre>
<p dir="auto">Скорость трассеровки должна в несколько раз увеличиться. К сожалению, смогу это узнать, когда перепишу текущий плагин.</p>
<p dir="auto">Там были уже сделаны изменения (все еще сырое для публикации плагина, пока не публикую)</p>
<blockquote>
<ul>
<li>Нумерация ветвей</li>
<li>Клик на круг — переход в дефоттный дизассемблер</li>
<li>Подсвечивать выбранный круг</li>
<li>Перерасчет позиций, когда поменялся размер окна</li>
<li>Счетчики выполнений инструкций срабатывающих к обращению на адрес</li>
<li>Изменен способ рисования связей между ветвями</li>
<li>Контекстное меню Показать ветку</li>
<li>Контекстное меню Скрыть ветку</li>
<li>На скрытой ветви не показываются связи упрощая обзор. Код поднимается снизу вверх. Если одна ветвь ниже другой, то можно её скрыть. Ориентируемся по счетчикам хитов на инструкции</li>
<li>Контекстное меню Сброс хитов</li>
<li>Оптимизация поиска корневого цикла</li>
<li>Выделение связей</li>
<li>Оптимизация рисования новых свзей</li>
<li>Контекстное меню пауза/продолжение</li>
<li>Запуск из контекстного меню при выделеии адреса в главной таблице</li>
<li>При закрытии окна снимаются все брейкпоинты</li>
<li>Возможность ставить логи на запись из контекстного меню и на чтение в главной таблице CE</li>
</ul>
</blockquote>
]]></description><link>https://celua.ru/post/343</link><guid isPermaLink="true">https://celua.ru/post/343</guid><dc:creator><![CDATA[MasterGH]]></dc:creator><pubDate>Sat, 20 May 2023 21:33:49 GMT</pubDate></item></channel></rss>