node/lib/metasm/metasm/disassemble.rb
def detect_function_thunk(funcaddr)
		# check thunk linearity (no conditionnal branch etc)
		addr = funcaddr
		count = 0
		while b = block_at(addr)
			count += 1
			return if count > 5 or b.list.length > 5
			if b.to_subfuncret and not b.to_subfuncret.empty?
				return if b.to_subfuncret.length != 1
				addr = normalize(b.to_subfuncret.first)
				return if not b.to_normal or b.to_normal.length != 1
				# check that the subfunction is simple (eg get_eip)
				return if not sf = @function[normalize(b.to_normal.first)]
				return if not btb = sf.backtrace_binding
				btb = btb.dup
				btb.delete_if { |k, v| Expression[k] == Expression[v] }
				return if btb.length > 2 or btb.values.include? Expression::Unknown
			else
				return if not bt = b.to_normal
				if bt.include? :default
					addr = :default
					break
				elsif bt.length != 1
					return
				end
				addr = normalize(bt.first)
			end
		end
		fname = Expression[addr].reduce_rec
		if funcaddr != addr and f = @function[funcaddr]
			# forward get_backtrace_binding to target
			f.backtrace_binding = { :thunk => addr }
			f.noreturn = true if @function[addr] and @function[addr].noreturn
		end
		return if not fname.kind_of? ::String
		l = auto_label_at(funcaddr, 'sub', 'loc')
		return if l[0, 4] != 'sub_'
		puts "found thunk for #{fname} at #{Expression[funcaddr]}" if $DEBUG
		rename_label(l, @program.new_label("thunk_#{fname}"))
	end
# checks if the function starting at funcaddr is an external function thunk (eg jmp [SomeExtFunc])
# the argument must be the address of a decodedinstruction that is the first of a function,
#  which must not have return_addresses
# returns the new thunk name if it was changed
checks if the function starting at funcaddr is an external function thunk
the argument must be the address of a decodedinstruction that is the first of a function,
which must not have return_addresses
returns the new thunk name if it was changed
checks if the function starting at funcaddr is an external function thunk the argument must be the address of a decodedinstruction that is the first of a function which must not have return_addresses returns the new thunk name if it was changed
def detect_function_thunk(funcaddr)
		addr = funcaddr
		count = 0
		while b = block_at(addr)
			count += 1
			return if count > 5 or b.list.length > 5
			if b.to_subfuncret and not b.to_subfuncret.empty?
				return if b.to_subfuncret.length != 1
				addr = normalize(b.to_subfuncret.first)
				return if not b.to_normal or b.to_normal.length != 1
				return if not sf = @function[normalize(b.to_normal.first)]
				return if not btb = sf.backtrace_binding
				btb = btb.dup
				btb.delete_if { |k, v| Expression[k] == Expression[v] }
				return if btb.length > 2 or btb.values.include? Expression::Unknown
			else
				return if not bt = b.to_normal
				if bt.include? :default
					addr = :default
					break
				elsif bt.length != 1
					return
				end
				addr = normalize(bt.first)
			end
		end
		fname = Expression[addr].reduce_rec
		if funcaddr != addr and f = @function[funcaddr]
			f.backtrace_binding = { :thunk => addr }
			f.noreturn = true if @function[addr] and @function[addr].noreturn
		end
		return if not fname.kind_of? ::String
		l = auto_label_at(funcaddr, 'sub', 'loc')
		return if l[0, 4] != 'sub_'
		puts "found thunk for #{fname} at #{Expression[funcaddr]}" if $DEBUG
		rename_label(l, @program.new_label("thunk_#{fname}"))
	end
def detect_function_thunk ( funcaddr ) addr = funcaddr count = 0 while b = block_at ( addr ) count += 1 return if count > 5 or b . list . length > 5 if b . to_subfuncret and not b . to_subfuncret . empty? return if b . to_subfuncret . length != 1 addr = normalize ( b . to_subfuncret . first ) return if not b . to_normal or b . to_normal . length != 1 return if not sf = @function [ normalize ( b . to_normal . first ) ] return if not btb = sf . backtrace_binding btb = btb . dup btb . delete_if { | k , v | Expression [ k ] == Expression [ v ] } return if btb . length > 2 or btb . values . include? Expression :: Unknown else return if not bt = b . to_normal if bt . include? :default addr = :default break elsif bt . length != 1 return end addr = normalize ( bt . first ) end end fname = Expression [ addr ] . reduce_rec if funcaddr != addr and f = @function [ funcaddr ] f . backtrace_binding = { :thunk => addr } f . noreturn = true if @function [ addr ] and @function [ addr ] . noreturn end return if not fname . kind_of? :: String l = auto_label_at ( funcaddr , 'sub' , 'loc' ) return if l [ 0 , 4 ] != 'sub_' puts "found thunk for #{fname} at #{Expression[funcaddr]}" if $DEBUG rename_label ( l , @program . new_label ( "thunk_#{fname}" ) ) end
checks if the function starting at funcaddr is an external function thunk (eg jmp [SomeExtFunc])
the argument must be the address of a decodedinstruction that is the first of a function,
which must not have return_addresses
returns the new thunk name if it was changed
checks if the function starting at funcaddr is an external function thunk ( eg jmp [ SomeExtFunc ] ) the argument must be the address of a decodedinstruction that is the first of a function which must not have return_addresses returns the new thunk name if it was changed
# check thunk linearity (no conditionnal branch etc) # check that the subfunction is simple (eg get_eip) # forward get_backtrace_binding to target
funcaddr