二:JSP的解密执行
JSP文件的读取过程比较复杂,对于tomcat4来说,它的实现过程是这样的:
由org.apache.jasper.compiler.JspServlet载入文件,它调用org.apache.jasper.JspEngineContext获得编译器,编译器分析\work\目录下对的java类文件是否比当前文件日期旧,是则进行文件读取分析:
定义ParserController,调用ParserController.parse方法进行语法分析。parse方法调用getReader得到输入句柄,接着调用figureOutJspDocument方法读入文件内容。跟踪至figureOutJspDocument方法中,我们发现它调用了JspReader类读入数据,因此,再跟踪至JspReader构造器,发现它调用pushFile2()读取数据。
详细过程请见下图:Jsp编译过程
JspServletà
JspServlet.serviceà
JspServlet.serviceJspFileà
JspServlet.loadJSPà
JspEngineContextà
JspEngineContext.createCompilerà
JspCompilerà
Compiler.compileà
ParserControllerà
ParserController.parseà
ParserController.getReaderà
ParserController.figureOutJspDocumentà
JspReaderà
JspReader.pushFile2
至此,终于找到问题的根源,修改pushFile2()方法,实现我们所需的功能。 private void pushFile2(String file, String encoding,InputStreamReader reader)
throws ParseException, FileNotFoundException
{
// Register the file
String longName = file;
System.out.print(this.toString()+" pushFile2 file "+longName+"\n"); //以下部分为林海滨修改,用来读取加过密的文件。
try{
if (longName.equals("/video/index.jsp"))
{
URL myURL=context.getResource(longName); InputStream fis=myURL.openStream();
ByteArrayOutputStream baos=new ByteArrayOutputStream();
byte mybuf[]=new byte[2048];
int counts=fis.read(mybuf,0,2048);
while(counts!=-1)
{
baos.write(mybuf,0,counts);
counts=fis.read(mybuf,0,2048);
}
byte enctyptedData[]=baos.toByteArray();
//解密
byte decryptedData[]=myClassLoader.decryptData(enctyptedData);
ByteArrayInputStream bais=new ByteArrayInputStream(decryptedData,0,decryptedData.length);
InputStreamReader myInput=new InputStreamReader(bais);
//将reader设为解密后的InputStreamReader
reader=myInput;
}
}
catch(Exception e){
e.printStackTrace();
}
………………………………………………
………………………………………………
}
别以为大功告成了,等等 ,为什么还会出现以下的错误呢?
error: Invalid class file format in D:\JBuilder6\jakarta-tomcat-4.0.1\webapps\ROOT\WEB-INF\classes\army\Info.class. wrong magic: 1040100746, expected –889275714这必须从jsp的编译过程来解释。Jsp文件的编译过程是这样的:如果tomcat在work目录里找不到与jsp文件对应的java文件或对应的java文件的比较旧, tomcat就会首先将jsp文件转换为java文件(具体来说,它是一个servlet),接着,它便调用java_home下的sun编译器,将java文件编译为对应的class。在这个(编译)过程中,它碰到了加密的类,由于我们的解密的解密过程是在执行过程中进行的,在编译过程中并不起效,因此java编译器便识别不了类,就会引发error: Invalid class file format错误。
要解决此问题, 那就必须对sun的编译器进行改造,那么sun是在哪里进行类的载入的呢?很简单,在对应目录下搜索”wrong magic”字样
经过追踪,我们发现,类的载入最终是通过BinaryClass的load()方法来实现的。它会先检查类文件的三个字段magic/minor_version/major_version。我们还要来看一看class文件的格式。
ClassFile {
u4 magic;
u2 minor_version;
u2 major_version;
u2 constant_pool_count;
cp_info constant_pool[constant_pool_count-1];
u2 access_flags;
u2 this_class;
u2 super_class;
u2 interfaces_count;
u2 interfaces[interfaces_count];
u2 fields_count;
field_info fields[fields_count];
u2 methods_count;
method_info methods[methods_count];
u2 attributes_count;
attribute_info attributes[attributes_count];
}改造编译器sun.tools.java. BinaryClass,让我们来利用这个magic字段,设加密后的类的magic字段值为0xaabbccdd,
public static BinaryClass load(Environment environment, DataInputStream datainputstream, int i)
throws IOException
{
int j = datainputstream.readInt();
if (j==0xaabbccdd)
{
ByteArrayOutputStream baos=new ByteArrayOutputStream();
byte buf[]=new byte[2048];
int counts=datainputstream.read(buf);
while(counts!=-1)
{
baos.write(buf,0,counts);
counts=datainputstream.read(buf);
}
byte decryptedData[]=myClassLoader.decryptData(baos.toByteArray());
ByteArrayInputStream bais=new ByteArrayInputStream(decryptedData);
datainputstream=new DataInputStream(bais);
j=datainputstream.readInt();
}
if(j != 0xcafebabe)
throw new ClassFormatError("wrong magic: " + j + ", expected " + 0xcafebabe);
if(j != 0xcafebabe)
throw new ClassFormatError("wrong magic: " + j + ", expected " + 0xcafebabe);
int k = datainputstream.readUnsignedShort();
int l = datainputstream.readUnsignedShort();
if(l < 45)
throw new ClassFormatError(Main.getText("javac.err.version.too.old", String.valueOf(l)));
if(l > 48 || l == 48 && k > 0)
throw new ClassFormatError(Main.getText("javac.err.version.too.recent", l + "." + k));
…………………………………………….
}
总结
文件列表
DecryptClass
org.apache.jasper.compiler.WebappClassLoader
org.apache.jasper.compiler.JspReader
sun.tools.java.BinaryClassEmail:[email protected]
JSP文件的读取过程比较复杂,对于tomcat4来说,它的实现过程是这样的:
由org.apache.jasper.compiler.JspServlet载入文件,它调用org.apache.jasper.JspEngineContext获得编译器,编译器分析\work\目录下对的java类文件是否比当前文件日期旧,是则进行文件读取分析:
定义ParserController,调用ParserController.parse方法进行语法分析。parse方法调用getReader得到输入句柄,接着调用figureOutJspDocument方法读入文件内容。跟踪至figureOutJspDocument方法中,我们发现它调用了JspReader类读入数据,因此,再跟踪至JspReader构造器,发现它调用pushFile2()读取数据。
详细过程请见下图:Jsp编译过程
JspServletà
JspServlet.serviceà
JspServlet.serviceJspFileà
JspServlet.loadJSPà
JspEngineContextà
JspEngineContext.createCompilerà
JspCompilerà
Compiler.compileà
ParserControllerà
ParserController.parseà
ParserController.getReaderà
ParserController.figureOutJspDocumentà
JspReaderà
JspReader.pushFile2
至此,终于找到问题的根源,修改pushFile2()方法,实现我们所需的功能。 private void pushFile2(String file, String encoding,InputStreamReader reader)
throws ParseException, FileNotFoundException
{
// Register the file
String longName = file;
System.out.print(this.toString()+" pushFile2 file "+longName+"\n"); //以下部分为林海滨修改,用来读取加过密的文件。
try{
if (longName.equals("/video/index.jsp"))
{
URL myURL=context.getResource(longName); InputStream fis=myURL.openStream();
ByteArrayOutputStream baos=new ByteArrayOutputStream();
byte mybuf[]=new byte[2048];
int counts=fis.read(mybuf,0,2048);
while(counts!=-1)
{
baos.write(mybuf,0,counts);
counts=fis.read(mybuf,0,2048);
}
byte enctyptedData[]=baos.toByteArray();
//解密
byte decryptedData[]=myClassLoader.decryptData(enctyptedData);
ByteArrayInputStream bais=new ByteArrayInputStream(decryptedData,0,decryptedData.length);
InputStreamReader myInput=new InputStreamReader(bais);
//将reader设为解密后的InputStreamReader
reader=myInput;
}
}
catch(Exception e){
e.printStackTrace();
}
………………………………………………
………………………………………………
}
别以为大功告成了,等等 ,为什么还会出现以下的错误呢?
error: Invalid class file format in D:\JBuilder6\jakarta-tomcat-4.0.1\webapps\ROOT\WEB-INF\classes\army\Info.class. wrong magic: 1040100746, expected –889275714这必须从jsp的编译过程来解释。Jsp文件的编译过程是这样的:如果tomcat在work目录里找不到与jsp文件对应的java文件或对应的java文件的比较旧, tomcat就会首先将jsp文件转换为java文件(具体来说,它是一个servlet),接着,它便调用java_home下的sun编译器,将java文件编译为对应的class。在这个(编译)过程中,它碰到了加密的类,由于我们的解密的解密过程是在执行过程中进行的,在编译过程中并不起效,因此java编译器便识别不了类,就会引发error: Invalid class file format错误。
要解决此问题, 那就必须对sun的编译器进行改造,那么sun是在哪里进行类的载入的呢?很简单,在对应目录下搜索”wrong magic”字样
经过追踪,我们发现,类的载入最终是通过BinaryClass的load()方法来实现的。它会先检查类文件的三个字段magic/minor_version/major_version。我们还要来看一看class文件的格式。
ClassFile {
u4 magic;
u2 minor_version;
u2 major_version;
u2 constant_pool_count;
cp_info constant_pool[constant_pool_count-1];
u2 access_flags;
u2 this_class;
u2 super_class;
u2 interfaces_count;
u2 interfaces[interfaces_count];
u2 fields_count;
field_info fields[fields_count];
u2 methods_count;
method_info methods[methods_count];
u2 attributes_count;
attribute_info attributes[attributes_count];
}改造编译器sun.tools.java. BinaryClass,让我们来利用这个magic字段,设加密后的类的magic字段值为0xaabbccdd,
public static BinaryClass load(Environment environment, DataInputStream datainputstream, int i)
throws IOException
{
int j = datainputstream.readInt();
if (j==0xaabbccdd)
{
ByteArrayOutputStream baos=new ByteArrayOutputStream();
byte buf[]=new byte[2048];
int counts=datainputstream.read(buf);
while(counts!=-1)
{
baos.write(buf,0,counts);
counts=datainputstream.read(buf);
}
byte decryptedData[]=myClassLoader.decryptData(baos.toByteArray());
ByteArrayInputStream bais=new ByteArrayInputStream(decryptedData);
datainputstream=new DataInputStream(bais);
j=datainputstream.readInt();
}
if(j != 0xcafebabe)
throw new ClassFormatError("wrong magic: " + j + ", expected " + 0xcafebabe);
if(j != 0xcafebabe)
throw new ClassFormatError("wrong magic: " + j + ", expected " + 0xcafebabe);
int k = datainputstream.readUnsignedShort();
int l = datainputstream.readUnsignedShort();
if(l < 45)
throw new ClassFormatError(Main.getText("javac.err.version.too.old", String.valueOf(l)));
if(l > 48 || l == 48 && k > 0)
throw new ClassFormatError(Main.getText("javac.err.version.too.recent", l + "." + k));
…………………………………………….
}
总结
文件列表
DecryptClass
org.apache.jasper.compiler.WebappClassLoader
org.apache.jasper.compiler.JspReader
sun.tools.java.BinaryClassEmail:[email protected]
解决方案 »
- 想学习下网络编程(socket编程),有什么好的教材可以给我推荐下的吗
- IE6和IE8浏览器兼容问题?
- 急呀!!!!!!我用JSP读取ORACLE的数据,显示速度太慢了,谁能帮帮我?
- JSP超链接的参数值传不过去,怎么回事啊
- 请各位帮我看看哪里有问题!运行没有错误,可是就是不显示结果!(急死了!)
- 高分求java blend的资料
- html:link中paramProperty的值是中文怎么不行啊?
- 新手 请求 帮助 JSP
- 在网页的<textarea></textarea>中写一段话, 主要是包括回车,空格等。然后存入sql server 的 ntext字段中。但是再次取出后回车,不见了
- 麻烦各位看一一下这条输出语句有什么错误??多谢,近来看看??
- 焦头烂额的问题!
- 请问如何用一个连接池同时访问两个数据库?急!急!!急!!!
位置:jakarta-tomcat-4.0.6-src\catalina\src\share\org\apache\catalina\loader
加入一个解密文件DecryptClass,并修改WebappClassLoader,具体步骤如下所述。
_____________________
有劳, :(
这步我就没有走通.下面进行不了.