node/lib/metasm/metasm/cpu/ia32/decode.rb
def name_local_vars(dasm, funcaddr)
		esp = register_symbols[4]
		func = dasm.function[funcaddr]
		subs = []
		dasm.trace_function_register(funcaddr, esp => 0) { |di, r, off, trace|
			next if r.to_s =~ /flag/
			if di.opcode.name == 'call' and tf = di.block.to_normal.find { |t| dasm.function[t] and dasm.function[t].localvars }
				subs << [trace[esp], dasm.function[tf].localvars]
			end
			di.instruction.args.grep(ModRM).each { |mrm|
				b = mrm.b || (mrm.i if mrm.s == 1)
				# its a modrm => b is read, so ignore r/off (not yet applied), use trace only
				stackoff = trace[b.symbolic] if b
				next if not stackoff
				imm = mrm.imm || Expression[0]
				frameoff = imm + stackoff
				if frameoff.kind_of?(::Integer)
					# XXX register args ? non-ABI standard register args ? (eg optimized x64)
					str = 'var_%X' % (-frameoff)
					str = 'arg_%X' % (frameoff-@size/8) if frameoff > 0
					str = func.get_localvar_stackoff(frameoff, di, str) if func
					imm = imm.expr if imm.kind_of?(ExpressionString)
					mrm.imm = ExpressionString.new(imm, str, :stackvar)
				end
			}
			off = off.reduce if off.kind_of?(Expression)
			next unless off.kind_of?(Integer)
			off
		}
		# if subfunctions are called at a fixed stack offset, rename var_3c -> subarg_0
		if func and func.localvars and not subs.empty? and subs.all? { |sb| sb[0] == subs.first[0] }
			func.localvars.each { |varoff, varname|
				subargnames = subs.map { |o, sb| sb[varoff-o+@size/8] }.compact
				if subargnames.uniq.length == 1
					varname.replace 'sub'+subargnames[0]
				end
			}
		end
	end
# trace the stack pointer register across a function, rename occurences of esp+XX to esp+var_XX
trace the stack pointer register across a function, rename occurences of esp+XX to esp+var_XX
trace the stack pointer register across a function rename occurences of esp + XX to esp + var_XX
def name_local_vars(dasm, funcaddr)
		esp = register_symbols[4]
		func = dasm.function[funcaddr]
		subs = []
		dasm.trace_function_register(funcaddr, esp => 0) { |di, r, off, trace|
			next if r.to_s =~ /flag/
			if di.opcode.name == 'call' and tf = di.block.to_normal.find { |t| dasm.function[t] and dasm.function[t].localvars }
				subs << [trace[esp], dasm.function[tf].localvars]
			end
			di.instruction.args.grep(ModRM).each { |mrm|
				b = mrm.b || (mrm.i if mrm.s == 1)
				stackoff = trace[b.symbolic] if b
				next if not stackoff
				imm = mrm.imm || Expression[0]
				frameoff = imm + stackoff
				if frameoff.kind_of?(::Integer)
					str = 'var_%X' % (-frameoff)
					str = 'arg_%X' % (frameoff-@size/8) if frameoff > 0
					str = func.get_localvar_stackoff(frameoff, di, str) if func
					imm = imm.expr if imm.kind_of?(ExpressionString)
					mrm.imm = ExpressionString.new(imm, str, :stackvar)
				end
			}
			off = off.reduce if off.kind_of?(Expression)
			next unless off.kind_of?(Integer)
			off
		}
		if func and func.localvars and not subs.empty? and subs.all? { |sb| sb[0] == subs.first[0] }
			func.localvars.each { |varoff, varname|
				subargnames = subs.map { |o, sb| sb[varoff-o+@size/8] }.compact
				if subargnames.uniq.length == 1
					varname.replace 'sub'+subargnames[0]
				end
			}
		end
	end
def name_local_vars ( dasm , funcaddr ) esp = register_symbols [ 4 ] func = dasm . function [ funcaddr ] subs = [ ] dasm . trace_function_register ( funcaddr , esp => 0 ) { | di , r , off , trace | next if r . to_s =~ / flag / if di . opcode . name == 'call' and tf = di . block . to_normal . find { | t | dasm . function [ t ] and dasm . function [ t ] . localvars } subs << [ trace [ esp ] , dasm . function [ tf ] . localvars ] end di . instruction . args . grep ( ModRM ) . each { | mrm | b = mrm . b || ( mrm . i if mrm . s == 1 ) stackoff = trace [ b . symbolic ] if b next if not stackoff imm = mrm . imm || Expression [ 0 ] frameoff = imm + stackoff if frameoff . kind_of? ( :: Integer ) str = 'var_%X' % ( - frameoff ) str = 'arg_%X' % ( frameoff - @size / 8 ) if frameoff > 0 str = func . get_localvar_stackoff ( frameoff , di , str ) if func imm = imm . expr if imm . kind_of? ( ExpressionString ) mrm . imm = ExpressionString . new ( imm , str , :stackvar ) end } off = off . reduce if off . kind_of? ( Expression ) next unless off . kind_of? ( Integer ) off } if func and func . localvars and not subs . empty? and subs . all? { | sb | sb [ 0 ] == subs . first [ 0 ] } func . localvars . each { | varoff , varname | subargnames = subs . map { | o , sb | sb [ varoff - o + @size / 8 ] } . compact if subargnames . uniq . length == 1 varname . replace 'sub' + subargnames [ 0 ] end } end end
trace the stack pointer register across a function, rename occurences of esp+XX to esp+var_XX
trace the stack pointer register across a function rename occurences of esp + XX to esp + var_XX
# its a modrm => b is read, so ignore r/off (not yet applied), use trace only # XXX register args ? non-ABI standard register args ? (eg optimized x64) # if subfunctions are called at a fixed stack offset, rename var_3c -> subarg_0
dasm
funcaddr