ITPub博客

首页 > Linux操作系统 > Linux操作系统 > oracle wrap加密包破解问题

oracle wrap加密包破解问题

原创 Linux操作系统 作者:regonly1 时间:2009-11-17 10:54:25 0 删除 编辑

之前从itpub上找到了关于Oracle10g下wrap包的破解方法:
http://www.itpub.net/thread-1154232-1-2.html
总得来说,Oracle加密的原理就是先对源码进行lz压缩lzstr,然后对压缩数据进行SHA-1运算得到40位的加密串shstr,然后将加密串与压缩串拼接得到shstr+lzstr,然后对拼接后的字符串进行Oracle双字符转换(转换表)。最后将转换后的字符串进行base64编码,最终得到wrap的加密串。
        上面提供的lz压缩是一个外置的java包来执行的amosunwrapper.deflate/inflate。但是在调用该包的过程中,如果字符串过长,则会出现报错的问题(并不直接由于java包引起)。一直想用Oracle本身提供的方法来实现lz解压缩。然后就发现了utl_compress这个工具,它提供了lz_compress和lz_uncompress两个方法。但是通过实际破解发现,利用这两个函数无法得到解压缩后的源码,都是抛出ora-29294压缩格式错误的问题。开始以为是中间raw转换过程或双字符转换过程出现了错误,但是用amosunwrapper解压缩却是可以的。最后经过实际比对发现,utl_compress.lz_compress压缩的数据和amosunwrapper.deflate压缩的数据格式上差别很大,而实际上我们通过实践,已经知道amosunwrapper.inflate能够正确解压wrap的压缩数据,因此怀疑utl_compress包进行的实际上不是lz压缩,而是其他格式。通过网上查询,的确发现是这个问题:
http://www.itpub.net/viewthread.php?tid=1179268&pid=14603596&page=1&extra=#pid14603596
这里描述的更加详细。
        原来utl_compress所采用的压缩格式实际上不是lz压缩,而使gzip压缩。不知道是不是Oracle为了防止自己的源码被轻易破解还是其他原因,用了gzip压缩算法替换lz算法来迷惑我们,让我们以为wrap的加密串根本不是lz压缩的。

以下是amosunwrapper和utl_comress两种压缩方式的比对:

with tmp1 as (select 'create function a' m from dual),
     tmp2 as (select utl_compress.lz_compress(utl_raw.cast_to_raw(m)) lzstr from tmp1),
     tmp3 as (select lzstr, dbms_crypto.Hash(lzstr, 3)||lzstr shlzstr from tmp2),
     tmp4 as (select lzstr, shlzstr, double_replace(shlzstr) repshlzstr from tmp3),
     tmp5 as (select dbms_ddl.wrap(m) wp from tmp1),
     tmp6 as (select utl_compress.lz_uncompress(lzstr) lz_uncompress,
                     amosunwrapper.inflate(lzstr) uw_uncompress,
                     amosunwrapper.deflate(m, 9) uw_compress
                from tmp2, tmp1)
select --utl_raw.cast_to_varchar2(utl_encode.base64_encode(repshlzstr)) base64decode,
       --substr(wp, instr(wp, chr(10), 1, 20) + 1) subwp,
       --utl_raw.cast_to_varchar2(lz_uncompress) lz_uncompress,
       --uw_uncompress,
       uw_compress,
       lzstr
  from tmp4, tmp5, tmp6;

以下是一个最简单的破解过程:

declare
    v_str varchar2(1000) := 'create or replace function a(x int, y out varchar2)' ;
    v_str_wrapped  varchar2(1000) := dbms_ddl.wrap(v_str);
    v_str1 varchar2(1000) := substr(v_str_wrapped, instr(v_str_wrapped, chr(10), 1, 20) + 1);
    v_str2 varchar2(1000) := replace(v_str1, chr(10));
    v_b64  raw(1000);
    v_cct  raw(1000);
    v_cps  raw(1000);
begin

    v_b64 := substr(utl_encode.base64_decode(utl_raw.cast_to_raw(v_str2)), 41);
 
    v_cct := double_replace(v_b64, 2);
    lyon.p(utl_raw.cast_to_raw(v_str2), 1);
    lyon.p(v_b64, 1);
    lyon.p(v_cct, 1);
    lyon.p(amosunwrapper.inflate(v_cct), 1);
    --lyon.p(utl_compress.lz_uncompress(v_b64), 1);

    --p(utl_compress.lz_uncompress(v_cct), 1);
    --p(utl_compress.lz_compress(utl_raw.cast_to_raw('function a')), 1);
end;

涉及到的函数和表:
create or replace function double_replace(str varchar2, xway int := 1)
return raw as
    type typ_dic is table of varchar2(2) index by varchar2(2);
    v_dic  typ_dic;
    v_ret  raw(1000);
begin
    if (xway = 1) then
        for c in (select il.* from sys.idltranslate il) loop
            v_dic(c.c_lzdeflatecode) := c.c_base64decode;
        end loop;
    elsif (xway = 2) then
        for c in (select il.* from sys.idltranslate il) loop
            v_dic(c.c_base64decode) := c.c_lzdeflatecode;
        end loop;   
    end if;
    for i in 0 .. length(str)/2 - 1 loop
        v_ret := v_ret || v_dic(substr(str, i*2 + 1, 2));
        --lyon.p('src: ' || substr(str, i*2 + 1, 2) || ' -> dst: ' || v_dic(substr(str, i*2 + 1, 2)), 1);
    end loop;
    return v_ret;
end double_replace;

--idtranslate表
create table IDLTRANSLATE
(
  C_BASE64DECODE  VARCHAR2(2) not null,
  C_LZDEFLATECODE VARCHAR2(2)
);

amosunwrapper就不提供了,想找的很容易找到。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/12932950/viewspace-619808/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2008-05-10

  • 博文量
    257
  • 访问量
    1070143