使用logic analyzer和python对JTAG调试器进行逆向工程

对JTAG调试器进行逆向工程

这篇文章展示了如何对一个jtag调试器进行”逆向工程“,使用逻辑分析仪采集jtag调试器的时序数据,导出成cvs格式数据,然后使用python进行数据处理生成C语言源代码。帮助分析提取jtag协议,完成jtag调试器的”逆向工程“。

对jtag调试器进行逆向工程,分析mcu的jtag协议,这是个巨大的工程,方法不对,根本做不出来。但是借助逻辑分析仪进行数据采集,用python进行数据处理,直接生产程序代码,看起来能很容易的取得调试器的协议。


msp430的jtag,官方只开源了烧写flash部分的源码和协议,至于单步调试,读写寄存器,断点设置等,都没有公开,只有几家商业公司掌握着,msp430开源社区里没这方面的任何进展。因此,我下定决心对fet430uif进行“逆向工程",完成arm板的jtag调试器,实现对msp430的gdb调试。


msp430的jtag使用的是4pin的jtag接口,TCK,TMS,TDI, TDO。使用agient logic analyzer采集jta个的时序,分别多次采集mspdebug的基本命令:读寄存器,写寄存器,单步,断点设置,运行,运行到断点等。

使用logic analyzer和python对JTAG调试器进行逆向工程_第1张图片


把采集到的数据保存好,再选着list数据(并非waveform数据)导出成cvs格式的数据格式,方便python读取分析。采集到的jtag数据量非常大,50ns的采样间隔,500ms就有160mb的数据。

使用logic analyzer和python对JTAG调试器进行逆向工程_第2张图片


msp430的jtag的基本操作只有shiftIR,shiftDR8,shiftDR16等几个,不多,用python写一个状态机,即可对这些数据进行处理。使用python对数据进行初步处理生成对应的jtag基本操作,生成一个只有几十kb的txt文本。


使用logic analyzer和python对JTAG调试器进行逆向工程_第3张图片


从采集的时序数据中初步得出了上面这些jtag基本操作的数据,这样进行分析手工编写代码,具有一定难度,工作量巨大。我再次使用python进行处理,生成C语言代码,为了方便阅读,还会自动生成一些简单的注释,生成的代码包含了宏定义。

使用logic analyzer和python对JTAG调试器进行逆向工程_第4张图片


这样,fet430uif调试器产生的时序,我都可以很方便的解释成C语言代码,分析出jtag协议,易如反掌。本来一个非常有难度的逆向工程,借助了逻辑分析仪与python就变得异常简单容易,大大减少了工作量。作为一个嵌入式工程师,学习掌握多种编程语言,对工作的帮助是不可估量。当初我学习python语言也是因为网上看到许多大牛对python的推崇,没想到却短期内给我的工作带来如此巨大的帮助。所以,尽量多学习掌握不同的语言,你永远也不知道它有多么重要,但它可能某一天帮了你一把。


附录python源码:

decode-msp430-jtag.py

import sys
import os
# TDO	-	data[0]
# TDI	-	data[1]
# TMS	-	data[2]
# TCK	-	data[3]

class DeShiftData:
	def __init__(self):
		self.data = "";
	
	def finish(self):
		data = ""
		if len(self.data) == 8:
			data = "0x%0.2X" % int(self.data, 2)
		else:
			data = "0x%0.4X" % int(self.data, 2) 
			
		self.data = ""
		return data
	
	def push(self, data):
		self.data = self.data + data
		
class TAPState:
	def __init__(self):
		self.state="IDLE"
		
	def change(self, tms):
		lastState = self.state
		if self.state == "IDLE":
			if tms == "0":
				pass
			else:
				self.state = "selectDRScan"
				
		elif self.state == "selectDRScan":
			if tms == "0":
				self.state = "captureDR"
			else:
				self.state = "selectRIScan"

		elif self.state == "captureDR":
			if tms == "0":
				self.state = "shiftDR"
			else:
				self.state = "exit1DR"
	
		elif self.state == "shiftDR":
			if tms == "0":
				#loop
				pass
			else:
				self.state = "exit1DR"		

		elif self.state == "exit1DR":
			if tms == "0":
				self.state = "pauseDR"	
			else:
				self.state = "updateDR"	
				
		elif self.state == "pauseDR":
			if tms == "0":
				#loop
				pass
			else:
				self.state = "exit2DR"		

		elif self.state == "exit2DR":
			if tms == "0":
				self.state = "shiftDR"	
			else:
				self.state = "updateDR"
		elif self.state == "updateDR":
			if tms == "0":
				self.state = "IDLE"	
			else:
				self.state = "selectDRScan"		
				
		#IR
		elif self.state == "selectRIScan":
			if tms == "0":
				self.state = "captureIR"
			else:
				self.state = "fuseCheck"

		elif self.state == "captureIR":
			if tms == "0":
				self.state = "shiftIR"
			else:
				self.state = "exit1IR"
	
		elif self.state == "shiftIR":
			if tms == "0":
				#loop
				pass
			else:
				self.state = "exit1IR"		

		elif self.state == "exit1IR":
			if tms == "0":
				self.state = "pauseIR"	
			else:
				self.state = "updateIR"	
				
		elif self.state == "pauseIR":
			if tms == "0":
				#loop
				pass
			else:
				self.state = "exit2IR"		

		elif self.state == "exit2IR":
			if tms == "0":
				self.state = "shiftIR"	
			else:
				self.state = "updateIR"
		elif self.state == "updateIR":
			if tms == "0":
				self.state = "IDLE"	
			else:
				self.state = "selectIRScan"								
		return (lastState,self.state)
	
#travel all lines in file

datafile = sys.argv[1]

last_data = "0110"
lastTime = "0 ns"
count=0
tap = TAPState()
dataIR = DeShiftData()
dataDR = DeShiftData()
dataOUT = DeShiftData()
count=0
for line in open(datafile):
	number,data,myTime = line.split(",")
	
	#skip first line
	
	try:
		data = bin(int(data, 16))[2:].zfill(4)
	except:
		print "#convererror line is: %s" % line
		continue
	
	#skip 
	if last_data == data or data[0] == "\"":
		continue
	

	
	lastTime = myTime
	TDO = data[0]
	TDI = data[1]
	TMS = data[2]
	TCK = data[3]	
		
	#pos edge
	if TCK == "1" and  last_data[3] == "0":
					
		#tap
		lastTapState,tapState = tap.change(TMS)

		if lastTapState == "captureIR" or lastTapState == "captureDR":
			#start a shitf
			pass
		elif tapState == "shiftIR" or lastTapState == "shiftIR":
			#print "shiftIR  " + TDI
			dataIR.push(TDI)
			if 	tapState == "exit1IR":
				irdata = dataIR.finish()
				print myTime.replace("\n", "") + " ShiftIR " + irdata
		elif tapState == "shiftDR" or lastTapState == "shiftDR":
			#print "shiftDR  " + TDI + "  " + TDO
			dataDR.push(TDI)
			dataOUT.push(TDO)
			if 	tapState == "exit1DR":
				drdata = dataDR.finish()
				outdata = dataOUT.finish()
				print myTime.replace("\n", "") + " ShiftDR " + drdata
				print myTime.replace("\n", "") + " = " + outdata
	
	if TDI != last_data[1] and tapState == "IDLE":
			if TDI == "0":
				print myTime.replace("\n", "") + " clrTCLK    0"
			else:
				print myTime.replace("\n", "") + " setTCLK    1"
	last_data = data



	
		


jtag-to-c.py

import sys

#travel all lines in file

datafile = sys.argv[1]

		
print """/*
 * %s
 */
""" % sys.argv[1]
codeDict = {"0xC8":"IR_CNTRL_SIG_16BIT", "0xc8":"IR_CNTRL_SIG_16BIT", 
		"0x88":"IR_CNTRL_SIG_M8BIT",
		"0x48":"IR_CNTRL_SIG_L8BIT",
		"0x28":"IR_CNTRL_SIG_CAPTURE",
		"0xA8":"IR_CNTRL_SIG_RELEASE", "0xa8":"IR_CNTRL_SIG_RELEASE",
		"0x44":"IR_PREPARE_BLOW",
		"0x24":"IR_EX_BLOW",
		"0x82":"IR_DATA_16BIT",
		"0xC2":"IR_DATA_QUICK", "0xc2":"IR_DATA_QUICK",
		"0x22":"IR_DATA_PSA",
		"0x62":"IR_SHIFT_OUT_PSA",
		"0xC1":"IR_ADDR_16BIT", "0xc1":"IR_ADDR_16BIT",
		"0x21":"IR_ADDR_CAPTURE",
		"0xA1":"IR_DATA_TO_ADDR", "0xa1":"IR_DATA_TO_ADDR",
		"0xFF":"IR_BYPASS", "0xff":"IR_BYPASS",
		"0x90":"IR_CTRL_SETTING",
		"0x30":"IR_30_SETTING",
		"0x42":"IR_DATA_CAPTURE",
		
		"0xD0": "IR_D0_CHECK", "0xd0": "IR_D0_CHECK"
		}

lastTime = "0"
for line in open(datafile):
	#print line.strip("\n")
	
	try:
		myTime, sym, operation, code =  line.split()
	except:
		print "//FIXME: error - line.split() %s" % line
		continue
	
	code = code.strip("\n")
	
	if sym != "us":
		interval = (float(myTime) - float(lastTime))
		if  interval > 0.1:
			print "\n//Interval  %F ms" % interval
			print "MsDelay(%d);" % int(interval)
		lastTime = myTime
				
	if operation == "ShiftIR":
		if codeDict[code] == "IR_CNTRL_SIG_CAPTURE":
			print "\n//fetch"
		elif codeDict[code] == "IR_CTRL_SETTING":
			print "\n//setting"
		elif codeDict[code] == "IR_D0_CHECK":
			print "\n//check"
		elif codeDict[code] == "IR_CNTRL_SIG_RELEASE":	
			print "\n//run"
			
		print "IR_Shift(" + codeDict[code] + ");"
	elif operation == "ShiftDR":
		if len(code) == 4:
			print "DR_Shift8(" + code + ");",
		else:
			print "DR_Shift16(" + code + ");",
	elif operation == "=":
		print "\t\t//=" + code
	elif operation == "clrTCLK": 
		print "ClrTCLK();"
	elif operation == "setTCLK": 
		print "SetTCLK();"
	
	


你可能感兴趣的:(msp430,jtag,学习经验,C语言编程)