首页
社区
课程
招聘
[转帖]一款JAVA商业软件的Class加密方法破解
2013-2-8 09:52 1219

[转帖]一款JAVA商业软件的Class加密方法破解

2013-2-8 09:52
1219
来源:黑吧 作者: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;
}

[培训]内核驱动高级班,冲击BAT一流互联网大厂工 作,每周日13:00-18:00直播授课

收藏
免费 0
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回