#!/usr/bin/awk -f

#
# 'kvld' Copyright (C) 2010 Columbia University
#
# This software was developed by Vasileios P. Kemerlis <vpk@cs.columbia.edu>
# at Columbia University, New York, NY, USA, in November 2010.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#
# 'kvld' (x86/x86-64 kGuard validator)
#
# 'kvld' is a simple AWK script that processes the output of `objdump -d'
# (GNU binutils) -- when the latter is applied on a kGuard-protected
# ELF binary -- and spits code snippets that are not confined, followed
# by an instrumentation summary.
#
# Usage: objdump -d <kobj> | cut -f3 | ./kvld
#
# <kobj>:
#	- vmlinux	(Linux kernel image; decompressed)
#	- *.ko		(Linux kernel module)
#	- *.o		(object file)
#

$0 == ""	{ next }

$0 ~ />:$/	{
			fun = substr($0, 1, length($0)-1)
			wnd[3] = wnd[2] = wnd[1] = wnd[0] = ""
		}

		{
			wnd[3] = wnd[2]
			wnd[2] = wnd[1]
			wnd[1] = wnd[0]
			wnd[0] = $0
		}

($0 ~ /^ret/) || ($0 ~ /\*/ && $0 ~ /^(call|jmp)/) {
			if(	(wnd[3] ~ /^(cmp|test)/)&&
				(wnd[2] ~ /^j/)		&&
				(wnd[1] ~ /^mov/)	) {
				if ($0 ~ /^ret/)
					cret++
				if ($0 ~ /^call/)
					ccall++
				if ($0 ~ /^jmp/)
					cjmp++
			}
			else {
				print "---[" fun "]---"
				if (wnd[3] != "")
					print wnd[3]
				if (wnd[2] != "")
					print wnd[2]
				if (wnd[1] != "")
					print wnd[1]
				print $0
				print ""

				if ($0 ~ /^ret/)
					uret++
				if ($0 ~ /^call/)
					ucall++
				if ($0 ~ /^jmp/)
					ujmp++
			}
		}

END		{
			print "x86/x86-64 kGuard validator"
			print "---------------------------"
			print "[-] unconfined"
			print "    'call':" ucall
			print "    'jmp' :" ujmp
			print "    'ret' :" uret
			print "[+] confined"
			print "    'call':" ccall
			print "    'jmp' :" cjmp
			print "    'ret' :" cret
		}
