-
-
[转帖]一款JAVA商业软件的Class加密方法破解
-
发表于: 2013-2-8 09:52 1289
-
来源:黑吧 作者:hnzzz 时间:2013-02-06 23:24:02
由于工作原因,经常与一款工业CAM软件打交道,对其中的一些算法非常感兴趣,便打算研究。
改软件核心代码全部是由JAVA写的,但是进行了加密,不能直接用反编译软件进行反编译。
查询运行java命令行发现其首先允许的是一个secure.jar中的SecureLoader类,此类没有进行加密。
使用JAVA反编译软件对SecureLoader进行反编译,可见其中存在如下native 方法的定义:
private native Class defineEncryptedClass(byte abyte0[], String s);
此native方法是在其secureloader.dll中定义的,用WIN32ASM打开,找到关键代码段如下:
:10001052 53 push ebx
:10001053 57 push edi
:10001054 6A04 push 00000004
:10001056 55 push ebp
:10001057 56 push esi
:10001058 FF9220030000 call dword ptr [edx+00000320]
:1000105E 57 push edi ;待解密数据长度
:1000105F 53 push ebx ;待解密数据的地址
:10001060 E85B050000 call 100015C0 ;解密函数
:10001065 8B442424 mov eax, dword ptr [esp+24]
:10001069 83C408 add esp, 00000008
:1000106C 85C0 test eax, eax
:1000106E 0F84AE000000 je 10001122
:10001074 50 push eax
* Reference To: MSVCRT.??2@YAPAXI@Z, Ord:000Fh
|
:10001075 E84C0D0000 Call 10001DC6
:1000107A 83C404 add esp, 00000004
:1000107D 8BE8 mov ebp, eax
:1000107F 6A04 push 00000004
:10001081 6A04 push 00000004
:10001083 6A04 push 00000004
:10001085 6A04 push 00000004
:10001087 6A04 push 00000004
:10001089 6A04 push 00000004
:1000108B 6A04 push 00000004
:1000108D 6A04 push 00000004
:1000108F 6A02 push 00000002
:10001091 6860100000 push 00001060
:10001096 E895080000 call 10001930 ;调用lzo_init()函数
:1000109B 83C428 add esp, 00000028
:1000109E 85C0 test eax, eax
:100010A0 7419 je 100010BB
* Possible StringData Ref from Data Obj ->"lzo_init() failed !!!
"
|
:100010A2 683C300010 push 1000303C
* Reference To: MSVCRT.printf, Ord:029Bh
|
:100010A7 FF1508200010 Call dword ptr [10002008]
:100010AD 83C404 add esp, 00000004
:100010B0 6A01 push 00000001
* Reference To: MSVCRT.exit, Ord:0246h
|
:100010B2 FF151C200010 Call dword ptr [1000201C]
:100010B8 83C404 add esp, 00000004
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:100010A0(C)
|
:100010BB 8B44241C mov eax, dword ptr [esp+1C]
:100010BF 8D4C2414 lea ecx, dword ptr [esp+14]
:100010C3 6A00 push 00000000
:100010C5 51 push ecx
:100010C6 55 push ebp
:100010C7 57 push edi
:100010C8 53 push ebx
:100010C9 89442428 mov dword ptr [esp+28], eax
:100010CD E80E090000 call 100019E0 ;调用lzo_decompress()函数进行解密
:100010D2 83C414 add esp, 00000014
对于解密方法和解压缩方法没必要进行详细研究,直接调用其函数即可,由此我写了一个类来实现,具体如下:
头文件:
#pragma once
#define LZO_E_OK (0)
typedef int (*LZO_INIT)(unsigned v, int s1, int s2, int s3, int s4, int s5,
int s6, int s7, int s8, int s9);
typedef int (*LZO_DECOMPRESS)( const BYTE * in , DWORD in_len, BYTE * out, DWORD* out_len,int wrkmem);
typedef void(*XXX_DECODER)(BYTE *in,DWORD in_len);
class CLzoDecompress
{
public:
CLzoDecompress(void);
~CLzoDecompress(void);
private:
CString m_strDLLName;
HMODULE m_hDLL;
DWORD dwOff_init;
DWORD dwOff_prevTreat;
DWORD dwOff_decomp;
DWORD dwOff_check;
LZO_INIT fn_lzo_init;
LZO_DECOMPRESS fn_lzo_decompress;
xxx_DECODER fn_xxx_decoder;
private:
bool CheckOffset(const BYTE * buff)
{
return (BYTE)buff[0] == (BYTE)0xE8 && (BYTE)buff[1] == (BYTE)0x0E && (BYTE)buff[2] == (BYTE)0x09;
}
void Init()
{
m_strDLLName = "secureloader.dll";
dwOff_init = 0x00001930;
dwOff_prevTreat=0x000015C0;
dwOff_decomp = 0x000019E0;
dwOff_check = 0x000010CD;
fn_lzo_init = NULL;
fn_lzo_decompress = NULL;
fn_xxx_decoder = NULL;
m_hDLL = LoadLibrary(m_strDLLName);
if(m_hDLL == NULL)
{
AfxMessageBox("LoadLibrary failed!");
return;
}
dwOff_check += (DWORD)m_hDLL;
BYTE * szBuff = (BYTE *) dwOff_check;
if(!CheckOffset(szBuff))
{
AfxMessageBox("CheckOffset failed!");
FreeLibrary(m_hDLL);
m_hDLL = NULL;
return;
}
fn_lzo_init = (LZO_INIT)((DWORD)m_hDLL + dwOff_init);
fn_lzo_decompress = (LZO_DECOMPRESS)((DWORD)m_hDLL + dwOff_decomp);
fn_xxx_decoder = (xxx_DECODER)((DWORD)m_hDLL + dwOff_prevTreat);
int r = fn_lzo_init(0x1060,2,4,4,4,4,4,4,4,4);
if(r != LZO_E_OK)
{
AfxMessageBox("lzo_init failed!\n");
FreeLibrary(m_hDLL);
m_hDLL = NULL;
return;
}
}
void Destroy()
{
if(m_hDLL!=NULL)
{
FreeLibrary(m_hDLL);
}
dwOff_init = 0;
dwOff_decomp = 0;
dwOff_check = 0;
fn_lzo_init = NULL;
fn_lzo_decompress = NULL;
fn_xxx_decoder = NULL;
}
public:
int LzoDecompress(LPCTSTR strFileIn, LPCTSTR strFileOut);
};
CPP文件
#include "StdAfx.h"
#include "LzoDecompress.h"
CLzoDecompress::CLzoDecompress(void)
{
Init();
}
CLzoDecompress::~CLzoDecompress(void)
{
Destroy();
}
int CLzoDecompress::LzoDecompress(LPCTSTR strFileIn, LPCTSTR strFileOut)
{
CFile in;
if(!in.Open(strFileIn,CFile::modeRead))
{
return -1;
}
CFile out;
if(!out.Open(strFileOut,CFile::modeCreate|CFile::modeReadWrite))
{
in.Close();
return -1;
}
//读取输入文件
DWORD dwInLen = (DWORD)in.GetLength();
BYTE *inBuff = (BYTE *)malloc(dwInLen);
dwInLen = in.Read(inBuff,dwInLen);
in.Close();
//解压缩
DWORD dwOutLen = 0;
DWORD offset = 4;
memcpy((void *)&dwOutLen,inBuff,4);
BYTE *outBuff = (BYTE *)malloc(dwOutLen);
ZeroMemory(outBuff,dwOutLen);
BYTE *inBuff2 = inBuff + offset;
fn_xxx_decoder(inBuff2,dwInLen - offset);
int ret = fn_lzo_decompress(inBuff2,dwInLen - offset,outBuff,&dwOutLen,0);
if(ret == LZO_E_OK)
{
out.Write(outBuff,dwOutLen);
}else
{
CString str;
str.Format("fn_lzo_decompress failed! %d",ret);
AfxMessageBox(str);
}
free(inBuff);
free(outBuff);
out.Close();
return ret;
}
由于工作原因,经常与一款工业CAM软件打交道,对其中的一些算法非常感兴趣,便打算研究。
改软件核心代码全部是由JAVA写的,但是进行了加密,不能直接用反编译软件进行反编译。
查询运行java命令行发现其首先允许的是一个secure.jar中的SecureLoader类,此类没有进行加密。
使用JAVA反编译软件对SecureLoader进行反编译,可见其中存在如下native 方法的定义:
private native Class defineEncryptedClass(byte abyte0[], String s);
此native方法是在其secureloader.dll中定义的,用WIN32ASM打开,找到关键代码段如下:
:10001052 53 push ebx
:10001053 57 push edi
:10001054 6A04 push 00000004
:10001056 55 push ebp
:10001057 56 push esi
:10001058 FF9220030000 call dword ptr [edx+00000320]
:1000105E 57 push edi ;待解密数据长度
:1000105F 53 push ebx ;待解密数据的地址
:10001060 E85B050000 call 100015C0 ;解密函数
:10001065 8B442424 mov eax, dword ptr [esp+24]
:10001069 83C408 add esp, 00000008
:1000106C 85C0 test eax, eax
:1000106E 0F84AE000000 je 10001122
:10001074 50 push eax
* Reference To: MSVCRT.??2@YAPAXI@Z, Ord:000Fh
|
:10001075 E84C0D0000 Call 10001DC6
:1000107A 83C404 add esp, 00000004
:1000107D 8BE8 mov ebp, eax
:1000107F 6A04 push 00000004
:10001081 6A04 push 00000004
:10001083 6A04 push 00000004
:10001085 6A04 push 00000004
:10001087 6A04 push 00000004
:10001089 6A04 push 00000004
:1000108B 6A04 push 00000004
:1000108D 6A04 push 00000004
:1000108F 6A02 push 00000002
:10001091 6860100000 push 00001060
:10001096 E895080000 call 10001930 ;调用lzo_init()函数
:1000109B 83C428 add esp, 00000028
:1000109E 85C0 test eax, eax
:100010A0 7419 je 100010BB
* Possible StringData Ref from Data Obj ->"lzo_init() failed !!!
"
|
:100010A2 683C300010 push 1000303C
* Reference To: MSVCRT.printf, Ord:029Bh
|
:100010A7 FF1508200010 Call dword ptr [10002008]
:100010AD 83C404 add esp, 00000004
:100010B0 6A01 push 00000001
* Reference To: MSVCRT.exit, Ord:0246h
|
:100010B2 FF151C200010 Call dword ptr [1000201C]
:100010B8 83C404 add esp, 00000004
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:100010A0(C)
|
:100010BB 8B44241C mov eax, dword ptr [esp+1C]
:100010BF 8D4C2414 lea ecx, dword ptr [esp+14]
:100010C3 6A00 push 00000000
:100010C5 51 push ecx
:100010C6 55 push ebp
:100010C7 57 push edi
:100010C8 53 push ebx
:100010C9 89442428 mov dword ptr [esp+28], eax
:100010CD E80E090000 call 100019E0 ;调用lzo_decompress()函数进行解密
:100010D2 83C414 add esp, 00000014
对于解密方法和解压缩方法没必要进行详细研究,直接调用其函数即可,由此我写了一个类来实现,具体如下:
头文件:
#pragma once
#define LZO_E_OK (0)
typedef int (*LZO_INIT)(unsigned v, int s1, int s2, int s3, int s4, int s5,
int s6, int s7, int s8, int s9);
typedef int (*LZO_DECOMPRESS)( const BYTE * in , DWORD in_len, BYTE * out, DWORD* out_len,int wrkmem);
typedef void(*XXX_DECODER)(BYTE *in,DWORD in_len);
class CLzoDecompress
{
public:
CLzoDecompress(void);
~CLzoDecompress(void);
private:
CString m_strDLLName;
HMODULE m_hDLL;
DWORD dwOff_init;
DWORD dwOff_prevTreat;
DWORD dwOff_decomp;
DWORD dwOff_check;
LZO_INIT fn_lzo_init;
LZO_DECOMPRESS fn_lzo_decompress;
xxx_DECODER fn_xxx_decoder;
private:
bool CheckOffset(const BYTE * buff)
{
return (BYTE)buff[0] == (BYTE)0xE8 && (BYTE)buff[1] == (BYTE)0x0E && (BYTE)buff[2] == (BYTE)0x09;
}
void Init()
{
m_strDLLName = "secureloader.dll";
dwOff_init = 0x00001930;
dwOff_prevTreat=0x000015C0;
dwOff_decomp = 0x000019E0;
dwOff_check = 0x000010CD;
fn_lzo_init = NULL;
fn_lzo_decompress = NULL;
fn_xxx_decoder = NULL;
m_hDLL = LoadLibrary(m_strDLLName);
if(m_hDLL == NULL)
{
AfxMessageBox("LoadLibrary failed!");
return;
}
dwOff_check += (DWORD)m_hDLL;
BYTE * szBuff = (BYTE *) dwOff_check;
if(!CheckOffset(szBuff))
{
AfxMessageBox("CheckOffset failed!");
FreeLibrary(m_hDLL);
m_hDLL = NULL;
return;
}
fn_lzo_init = (LZO_INIT)((DWORD)m_hDLL + dwOff_init);
fn_lzo_decompress = (LZO_DECOMPRESS)((DWORD)m_hDLL + dwOff_decomp);
fn_xxx_decoder = (xxx_DECODER)((DWORD)m_hDLL + dwOff_prevTreat);
int r = fn_lzo_init(0x1060,2,4,4,4,4,4,4,4,4);
if(r != LZO_E_OK)
{
AfxMessageBox("lzo_init failed!\n");
FreeLibrary(m_hDLL);
m_hDLL = NULL;
return;
}
}
void Destroy()
{
if(m_hDLL!=NULL)
{
FreeLibrary(m_hDLL);
}
dwOff_init = 0;
dwOff_decomp = 0;
dwOff_check = 0;
fn_lzo_init = NULL;
fn_lzo_decompress = NULL;
fn_xxx_decoder = NULL;
}
public:
int LzoDecompress(LPCTSTR strFileIn, LPCTSTR strFileOut);
};
CPP文件
#include "StdAfx.h"
#include "LzoDecompress.h"
CLzoDecompress::CLzoDecompress(void)
{
Init();
}
CLzoDecompress::~CLzoDecompress(void)
{
Destroy();
}
int CLzoDecompress::LzoDecompress(LPCTSTR strFileIn, LPCTSTR strFileOut)
{
CFile in;
if(!in.Open(strFileIn,CFile::modeRead))
{
return -1;
}
CFile out;
if(!out.Open(strFileOut,CFile::modeCreate|CFile::modeReadWrite))
{
in.Close();
return -1;
}
//读取输入文件
DWORD dwInLen = (DWORD)in.GetLength();
BYTE *inBuff = (BYTE *)malloc(dwInLen);
dwInLen = in.Read(inBuff,dwInLen);
in.Close();
//解压缩
DWORD dwOutLen = 0;
DWORD offset = 4;
memcpy((void *)&dwOutLen,inBuff,4);
BYTE *outBuff = (BYTE *)malloc(dwOutLen);
ZeroMemory(outBuff,dwOutLen);
BYTE *inBuff2 = inBuff + offset;
fn_xxx_decoder(inBuff2,dwInLen - offset);
int ret = fn_lzo_decompress(inBuff2,dwInLen - offset,outBuff,&dwOutLen,0);
if(ret == LZO_E_OK)
{
out.Write(outBuff,dwOutLen);
}else
{
CString str;
str.Format("fn_lzo_decompress failed! %d",ret);
AfxMessageBox(str);
}
free(inBuff);
free(outBuff);
out.Close();
return ret;
}
赞赏
他的文章
看原图
赞赏
雪币:
留言: