java字节码简介
java为了实现跨平台的特性,编写完代码,需要通过javac命令生产JVM所需要的class字节码文件。class文件是二进制的文件,里面存储的内容是16进制。通过javap命令可以查看具体的class信息,如下:
javap -c -s -v -l Crypto.class
![](https://img.haomeiwen.com/i24023302/f07609ccd6fe69a2.png)
在windows下也可以直接使用winhex工具打开:
![](https://img.haomeiwen.com/i24023302/83a0087664664727.png)
前四个字节是魔数的标识:0xCAFEBABE,16进制的固定值。后面的相关参数可以参考jvm的相关规范进行查找。
尝试使用xxtea进行加密
1、git clone https://github.com/xxtea/xxtea-c.git
![](https://img.haomeiwen.com/i24023302/b0e240cbb245b185.png)
2、cd到example目录下,并将上级目录的xxtea.c和xxtea.h拷贝到本目录下。
![](https://img.haomeiwen.com/i24023302/c6aedea4639f8508.png)
3、修改test.c文件
这里面需要注意的是,读取class字节的时候,需要使用unsigned char类型来存储,否则会出现越位问题:十六进制的CA会显示为ffffffCA。
字符输出的时候,以16进制输出:printf("%x\n", xxx);
#ifdef _WIN32
#pragma comment(lib, "xxtea.lib")
#endif
#include <stdio.h>
#include <string.h>
#include <xxtea.h>
#include "base64.h"
int main() {
FILE *fid;
fid = fopen("/root/Crypto.class","rb");
if(fid == NULL){
printf("读取文件出错");
return;
}
//获取文件大小
fseek (fid , 0 , SEEK_END);
long size = ftell (fid);
rewind (fid);
//开辟存储空间
int num = size/sizeof(char);
unsigned char *pos = (unsigned char*) malloc (sizeof(unsigned char)*num);
if (pos == NULL)
{
printf("开辟空间出错");
return;
}
fread(pos,sizeof(char),num,fid);
int i = 0;
for(i = 0; i < num; i++)
printf("%x\n", pos[i]);
fclose(fid);
const unsigned char *text = pos;
const char *key = "1234567890";
size_t len;
unsigned char *encrypt_data = xxtea_encrypt(text, num, key, &len);
char * base64_data = base64_encode(encrypt_data, len);
printf("%s\n", base64_data);
unsigned char *decrypt_data = xxtea_decrypt(encrypt_data, len, key, &len);
for(i = 0; i < num; i++)
printf("%x\n",decrypt_data[i]);
if (strncmp(text, decrypt_data, len) == 0) {
printf("success!\n");
}else {
printf("fail!\n");
}
free(pos); //释放内存
free(encrypt_data);
free(decrypt_data);
free(base64_data);
return 0;
}
编译源码
gcc test.c xxtea.c base64.c -o main
执行
./main
将输出的内容,拷贝到两个文本文件,然后使用对比工具进行比对,可以发现字节码加密后然后再解密与之前的能完全对得上。
结论
可以基于https://github.com/xxtea/xxtea-c.git项目实现对class文件的加解密。
网友评论