參考文檔:ORACLE_TNS協議.doc
用於分析截獲的TNS數據(只處理了連接請求和sql語句)
/**
* 用於分析TNS協議數據
* @author shanl
*
*/
public class TNSAnalysis {
// private DecimalFormat df = new DecimalFormat("###.#%");
private static final int HEADER_LENGTH = 8;
private byte[] data = null;
private int dataLen = 0;
/**
* 設置tns請求數據
* @param tnsData
* @param tnsDataLen
*/
public void setData(byte[] tnsData, int tnsDataLen){
this.data = tnsData;
this.dataLen = tnsDataLen;
}
/**
* 返回請求類型
* @return 1:連接,6:數據
*/
public int getType(){
return 0x00ff & (data[4]);
}
/**
* 返回連接請求數據
* @return
*/
public String getConnectData(){
int offset = HEADER_LENGTH;
int dataLen = (0xff00&(data[offset+16]<<2)) | (0x00ff&data[offset+17]);
int dataOffset = (0xff00&(data[offset+18]<<2)) | (0x00ff&data[offset+19]);
if(dataLen<0){
return "";
}
return new String(data, dataOffset, dataLen);
}
/**
* 解析oracle sql語句<br/>
* 只解析符合sql命令的數據
* @return 如果返回"",表示返回的不是sql命令。否則返回sql數據。
*/
public String getSqlData(){
String sql = "";
byte[] buffer = new byte[1024*1024*2];
int position = 0;
int c = 0;
int len = 0;
if(dataLen <= 142){
// System.out.println("非sql命令.");
return "";
}
//035E
if(0x03==data[10] && 0x5E==data[11]){
// System.out.println("035E");
//+82
c = 11 + 82;
//0xFE 大數量標誌,下面從0xFE下一個字節開始
//1+n(字節) 1表示長度,n爲數據; 1字節爲0表示數量結束.
if((byte)0xFE == data[c]){
do{
len = data[++c];
for(int i=c+1,end=i+len; i<end; i++){
// System.out.print((char)bys[i]);
// sql += (char)bys[i];
if(0x00 != data[i]){
buffer[position++] = data[i];
}
}
c += len;
}while(len!=0);
}else{//非大數量
len = data[c];
for(int i=c+1,end=i+len; i<end; i++){
// System.out.print((char)bys[i]);
// sql += (char)bys[i];
buffer[position++] = data[i];
}
}
}
//1169
if(0x11==data[10] && 0x69==data[11]){
// System.out.println("1169");
//+14
c = 11+14;
if(0x03==data[c] && 0x5E==data[++c]){
// System.out.println("035E");
}
//+82
c += 82;
//0xFE 大數量標誌,下面從0xFE下一個字節開始
//1+n(字節) 1表示長度,n爲數據; 1字節爲0表示數量結束.
if((byte)0xFE == data[c]){
while(0!=(len = data[++c])){
for(int i=c+1,end=i+len; i<end; i++){
// System.out.print((char)bys[i]);
// sql += (char)bys[i];
if(0x00 != data[i]){
buffer[position++] = data[i];
}
}
c += len;
}
}else{//非大數量
len = data[c];
for(int i=c+1,end=i+len; i<end; i++){
// System.out.print((char)bys[i]);
// sql += (char)bys[i];
if(0x00 != data[i]){
buffer[position++] = data[i];
}
}
}
}
sql = new String(buffer, 0, position);
return sql;
// return doFilter(sql);
}
}
測試類:
public class Test3 {
public static void main(String[] args){
t1();
}
static void t1(){
String hexStr = "012B00000600000000001169"
+"08E03868030100000001000"
+"000035E0961800000000000"
+"00204D68032802000088EA6"
+"7030C00000000000000B8EA"
+"67030000000000000000000"
+"00000000000000000000000"
+"00000000000000000000000"
+"0000000BAEA6703F4386803"
+"00000000FE4073656C65637"
+"4206772616E7465652C206E"
+"616D652066726F6D0A73797"
+"32E706C73716C6465765F61"
+"7574686F72697A6174696F6"
+"E0A7768657265206772616E"
+"7440656520696E202875736"
+"5722C20275055424C494327"
+"290A6F72206772616E74656"
+"520696E202873656C656374"
+"20726F6C652066726F6D207"
+"379732E73657373690A6F6E"
+"5F726F6C6573290A0001000"
+"00000000000000000000000"
+"00000000000000000000000"
+"00000010000000000000000"
+"0000000000000000000000";
// String hexStr = "00F00000010000000138012C000008007FFF860E0000010000B6"
// +"003A000002006161000000000000000000000E38000000140000000000000"
// +"000284445534352495054494F4E3D28414444524553533D2850524F544F43"
// +"4F4C3D5443502928484F53543D3139322E3136382E322E32332928504F525"
// +"43D31353231292928434F4E4E4543545F444154413D28534552564943455F"
// +"4E414D453D697032356F72636C29284349443D2850524F4752414D3D443A5"
// +"C746F6F6C735C504C53514C20446576656C6F7065725C504C53514C446576"
// +"2E6578652928484F53543D504336372928555345523D7368616E6C29292929";
byte[] bys = new byte[hexStr.length()/2];
int hex = 0;
int c = 0;
int len = 0;
for(int i=0,j=0,endi=hexStr.length()-2; i<endi; j++){
hex = Integer.valueOf(hexStr.substring(i, i+=2), 16);
bys[j] = (byte)hex;
// System.out.print(c+":"+h+" ");
}
TNSAnalysis tnsAnaly = new TNSAnalysis();
tnsAnaly.setData(bys, bys.length);
int type = tnsAnaly.getType();
System.out.println("tns type:"+type);
String tmp = null;
switch(type){
case 1: //連接請求
tmp = tnsAnaly.getConnectData();
break;
case 6: //sql語句
tmp = tnsAnaly.getSqlData();
break;
default:
}
System.out.println(tmp);
}
}