HP Builder 的密码加密url的破解

0x0 背景

在某个站发现了一套输入密码然后跳转url的方式

扒了下发现全程运算是在本地js的,与后台服务器无通信

来看一下原始代码

function _HpbChkPwd(keyin,escEncrypted,defaultUrl,target)
{
    var encrypted = unescape(escEncrypted);
    var indexbase = " !\"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
    var passlen = keyin.length;
    var enqlen  = encrypted.length;
    var decrypted = "";
    var decryptedPassword = "";
    var decryptedPath     = "";
    var targetUrl         = "";
    var i, j, k, chr1, chr2, nbase;
    var needPassword = "%u30D1%u30B9%u30EF%u30FC%u30C9%u3092%u5165%u529B%u3057%u3066%u304F%u3060%u3055%u3044%u3002";
    var badPassword  = "%u30D1%u30B9%u30EF%u30FC%u30C9%u304C%u6B63%u3057%u304F%u3042%u308A%u307E%u305B%u3093%u3002";
    if (passlen <= 0)
    {
        alert(unescape(needPassword));
        return ;
    }
    for (i = 0, j = passlen - 1, k = 0 ; i < enqlen ; i++, j--, k=0)
    {
        if (j < 0)
        {
            j = passlen - 1;
        }
        chr1 = indexbase.indexOf(keyin.charAt(j));
        chr2 = indexbase.indexOf(encrypted.charAt(i));
        if (chr2 < (chr1 + j))
        {
            nbase = (chr1 + j - chr2) / 0x5f;
            k += (0x5f * Math.ceil(nbase));
        }
        k += (chr2 - chr1 - j);
        decrypted += indexbase.charAt(k);
    }

    decryptedPassword = decrypted.substring(decrypted.length - passlen, decrypted.length);
    if (keyin == decryptedPassword)
    {
        decryptedPath = decrypted.substring(0, decrypted.length - passlen);
        passlen       = decryptedPath.length;
        for (i = 0 ; i < passlen ; i++)
        {
            chr1 = decryptedPath.charAt(i);
            if (chr1 == "%")
            {
                chr2 = decryptedPath.substring(i, i+6);
                targetUrl += chr2;
                i += 11;
            }
            else
                targetUrl += chr1;
        }
        if ((typeof(opener.closed) != "unknown") && ! opener.closed)
            opener.location.href = targetUrl;
        window.close();
    }
    else
    {
        if (defaultUrl.length)
        {
            if ((typeof(opener.closed) != "unknown") && ! opener.closed)
                opener.location.href = defaultUrl;
        }
        else
        {
            alert(unescape(badPassword));
        }
        window.close();
    }

0x1 分析

从上述源码中可以推论出如下

  1. 密钥的加密结果会附在密文后:
for (i = 0, j = passlen - 1, k = 0 ; i < enqlen ; i++, j--, k=0)
    {
        if (j < 0)
        {
            j = passlen - 1;
        }
        chr1 = indexbase.indexOf(keyin.charAt(j));
        chr2 = indexbase.indexOf(encrypted.charAt(i));
        if (chr2 < (chr1 + j))
        {
            nbase = (chr1 + j - chr2) / 0x5f;
            k += (0x5f * Math.ceil(nbase));
        }
        k += (chr2 - chr1 - j);
        decrypted += indexbase.charAt(k);
    }

    decryptedPassword = decrypted.substring(decrypted.length - passlen, decrypted.length);
    if (keyin == decryptedPassword)
    {
        decryptedPath = decrypted.substring(0, decrypted.length - passlen);

对于输入的密码 Keyin[],逆序平铺在每个加密字节上,即明文10位,密钥5位,密文=PPPPPPPPPPKKKKK

  1. 解密方法如下,明文正序,密钥循环逆序

    密文Byte[] 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
    密钥 4 3 2 1 0 4 3 2 1 0 4 3 2 1 0
    明文 ? ? ? ? ? ? ? ? ? ? 密钥[0] 密钥[1] 密钥[2] 密钥[3] 密钥[4]

    可列部分等式:

    密文[10]+4+密钥[4]=密钥[0]

    密文[11]+3+密钥[3]=密钥[1]

    密文[12]+2+密钥[2]=密钥[2]

    密文[13]+1+密钥[1]=密钥[3]

    密文[14]+0+密钥[0]=密钥[4]

​ 这里相加后是对照第一部分的IndexBase,当成一个Base95的ASCII表

  1. 第二步之后已经可以获得若干位密钥,接下来进入下一步破解

    解密出的明文为一个跳转url,在大多数情况下为.htm或.html结尾,因此可以额外列出等式

    密文Byte[] 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
    密钥 4 3 2 1 0 4 3 2 1 0 4 3 2 1 0
    明文 ? ? ? ? ? . h t m l 密钥[0] 密钥[1] 密钥[2] 密钥[3] 密钥[4]

​ 或者,对于一个很长的明文,可以猜测前缀为http://

密文Byte[] 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
密钥 4 3 2 1 0 4 3 2 1 0 4 3 2 1 0
明文 h t t p : ? ? ? ? ? 密钥[0] 密钥[1] 密钥[2] 密钥[3] 密钥[4]

​ 由此,可以列出其他等式

​ 密文[5]+4+密钥[4]="."

​ ...以此类推

0x2 解密

function start(n,escEncrypted)
{   
    var encrypted = unescape(escEncrypted);
    var indexbase = " !\"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
    var str = ".html";
    var arr=[]
    var arr2=[]
    for(i=0;i

核心代码差不多就这样,因为密钥长度不确定,需要当做参数输入,也可以自动从4开始进行试探

0x4 遗留问题

因为是通过猜测和取巧的方式进行破解,偶尔会出现长密码下几个字符的公式互相重合

此时再上暴力破解即可

0X5 参考资料

https://github.com/s-horiguchi/HPBPwdBreaker
http://www.usamimi.info/~geko/arch_web/03_memo/011_hpb/index.html

知识共享许可协议
本文采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
暂无评论

发送评论 编辑评论


|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
Copyright 2019-2023 © Livehouse-猫铃-
Theme Argon