krpano-1.19-pr10不是很完美爆破思路
本帖最后由 lxyg06 于 2017-6-12 14:01 编辑同事要求破解一个软件,事先声明 ,本人没有用过这款软件,但是注册码这些都是旧的krpano-1.19-pr8的,因为注册码里的信息就是注册人填写后通过加密后得到的,但是本人没有找到加密方法,所以就不能生产新的加密秘钥了。只有64位的那个文件破解了,32位的我没有破解,因为我只有64位的电脑
旧版本秘钥:
ruza4tk2X4MdHuE7djJQGr9QTftMFHiSH2ac5jkIlFgGqG0K0IVQnh5vF/
cicLpwedsURI0QTg+UluEgysRLUytpeVFyBTxdwREEIGquRh1Hp2BY2EtZ8kdO2r6CHLJAFlzY5w6au1rnHwRhJXgaK8J75RwK1DYb/
OEZ4tD2pniUrnMrpFwGWwcKnxGyNSmMktsU6qadFjKbMH3HUKNXa7Y59lEzbDZJbsTuP+UynwwBhogv8K+byjs2LDvU48sx4/
CNHWi26g==
注册成功的页面(网上好像也是加了马赛克 , 我也加一下)
通过关键字等都不能找到关键字,通过界面观察发现这个注册页面很像是网页的形式(本人是web程序员,所以对页面效果比较熟悉),但是无论我这么搜索,就没有找到这个页面或者在软件里面找到关键字。
偶然的机会 使用了FileLocatorPortable这个全文搜索,搜索到了里面的注册东西,
发现,原来页面被打包到这个软件里面了。
通过提取里面的信息如下
找到了一个关键字"error;lz=",然后用软件搜索,果然有个(事后整理发现带上这个是说注册码是无效的,但是不是错误的。)
满怀欣喜的下了个断点,但是程序竟然没有断下来,通过阅读js代码
function ID(e) {
return document.getElementById(e)
}
function gui_iframe_close_callback() {
top.gui_contextmenu_remove_editmenu(ID("code"))
}
function buylink(e) {
var t = top.nwrequire("nw.gui");
t.Shell.openExternal("http://krpano.com/buy/#top")
}
function helplink(e) {
var t = top.nwrequire("nw.gui");
t.Shell.openExternal("http://krpano.com/buy/howtoregister/#top")
}
function showerror_done() {
var e = ID("code");
stoptween(e),
e.style.opacity = 1,
e.select();
var t = ID("codeerror");
stoptween(t),
t.style.opacity = 0,
t.style.display = "none",
t.dataset.waittimer && (clearTimeout(t.dataset.waittimer), delete t.dataset.waittimer),
ID("regbutton").disabled = ""
}
function showokay_done() {
var e = ID("code");
e.value = "";
var t = ID("codeokay");
stoptween(t),
t.style.display = "none",
t.dataset.waittimer && (clearTimeout(t.dataset.waittimer), delete t.dataset.waittimer)
}
function registercode() {
var e = ID("regbutton"),
t = ID("code"),
n = ("" + t.value).trim();
n != "" && (e.disabled = "disabled", top.krpanotools.registerCode(n,
function(n) {
var r = 0;
if (n.slice(0, 9) == "error;lz=") {
r = parseInt(n.slice(9)),
n = "";
var i = r & 1,
s = r & 2,
o = r & 4,
u = ID("lickl"),
a = ID("licmp"),
f = ID("licbf");
u.checked = i ? "checked": "",
u.disabled = i ? "": "disabled",
a.checked = s ? "checked": "",
a.disabled = s ? "": "disabled",
f.checked = o ? "checked": "",
f.disabled = o ? "": "disabled";
var l = ID("errormsg");
l.innerHTML = "REGISTERING CODE FAILED" + (i == 0 ? "<br>Missing base krpano License!": ""),
i == 0 && (ID("lickltxt").style.color = "red")
}
if (n == "") {
var c = ID("codeerror");
c.style.opacity = 1,
c.style.display = "",
t.style.opacity = .25,
c.dataset.waittimer = setTimeout(function() {
tween_style(t, "opacity", 1, .25),
tween_style(c, "opacity", 0, .25, showerror_done)
},
3e3)
} else updatereginfos(n, !0),
e.disabled = ""
}))
}
function updatereginfos(e, t) {
var n = ID("reginfo"),
r = ID("notreginfo"),
i = ID("removelic"),
s = ID("regname"),
o = ID("regmail"),
u = ID("regdate"),
a = ID("contact"),
f = ID("address"),
l = ID("lickl"),
c = ID("licmp"),
h = ID("licbf"),
p = ID("buylic"),
d = 0;
top.app_update_reginfo(e);
if (e) {
var v = e.split(";"),
m = {},
g;
for (g = 0; g < v.length; g++) {
var y = v.split("=");
y.length == 2 && (m] = y)
}
m.lz && (d = parseInt(m.lz));
if (d > 0 && m.regname && m.regmail && m.orddate && m.contact && m.address) {
s.innerHTML = m.regname,
o.innerHTML = m.regmail,
u.innerHTML = m.orddate,
a.innerHTML = m.contact,
f.innerHTML = m.address,
ID("reg_contact").style.display = m["regname"] == m["contact"] ? "none": "",
ID("reg_filler1").style.display = m["regname"] == m["contact"] ? "": "none",
ID("reg_address").style.visibility = m["address"] == "..." ? "hidden": "visible";
if (t) {
ID("code").value = " ";
var b = ID("codeokay");
b.style.opacity = 1,
b.style.display = "",
tween_style(n, "opacity", 1, .5),
tween_style(r, "opacity", 0, .1),
tween_style(i, "opacity", 1, .5),
b.dataset.waittimer = setTimeout(function() {
ID("code").value = "",
tween_style(b, "opacity", 0, .25, showokay_done)
},
1e3)
} else n.style.opacity = 1,
r.style.opacity = 0,
i.style.opacity = 1;
var w = d & 1,
E = d & 2,
S = d & 4;
l.checked = w ? "checked": "",
l.disabled = w ? "": "disabled",
c.checked = E ? "checked": "",
c.disabled = E ? "": "disabled",
h.checked = S ? "checked": "",
h.disabled = S ? "": "disabled",
p.style.visibility = (d & 7) == 7 ? "hidden": "visible";
return
}
}
s.innerHTML = "",
o.innerHTML = "",
u.innerHTML = "",
a.innerHTML = "",
f.innerHTML = "",
ID("reg_contact").style.display = "",
ID("reg_filler1").style.display = "none",
ID("reg_address").style.visibility = "visible",
n.style.opacity = 0,
r.style.opacity = 1,
i.style.opacity = 0,
l.checked = "",
l.disabled = "disabled",
c.checked = "",
c.disabled = "disabled",
h.checked = "",
h.disabled = "disabled",
p.style.visibility = "visible"
}
function removelic() {
top.krpanoui.confirmDialog({
"native": !0,
title: "Remove Registration",
infotext: "Are you sure you want to remove the krpano registration from this computer?",
onclose: function(e) {
e && top.krpanotools.removeRegistration(function() {
updatereginfos("", !0)
})
}
})
}
top.gui_style_do_system_fixes(document),
top.gui_block_external_dragging(document);
var code_textarea = ID("code");
top.gui_contextmenu_assign_editmenu(code_textarea),
code_textarea.addEventListener("input",
function(e) {
ID("regbutton").disabled = code_textarea.value == "" ? "disabled": ""
},
!0),
top.krpanotools.getRegInfo(function(e) {
updatereginfos(e, !1)
}),
ID("reginfo").addEventListener("selectstart",
function(e) {
e.stopPropagation()
},
!0)
发现是如果注册码有问题才可以,所以就往上查询,下断点,下的断点就是跳过这个地方的代码。发现有三个地方
每个地方下断点,发现只有这个地方是关键断
000000013FEECC94 | 48 8B CE | mov rcx,rsi |
000000013FEECC97 | E8 84 87 F9 FF | call krpanotools64.13FE85420 |
000000013FEECC9C | 83 F8 01 | cmp eax,1 |
000000013FEECC9F | 0F 85 30 01 00 00 | jne krpanotools64.13FEECDD5 |
000000013FEECCA5 | 48 C7 45 E8 0F 00 | mov qword ptr ss:,F |
000000013FEECCAD | 48 C7 45 E0 00 00 | mov qword ptr ss:,0 |
000000013FEECCB5 | C6 45 D0 00 | mov byte ptr ss:,0 |
发现eax=1的时候才能不跳转(有人会问为什么其他的都不是,只是因为和krpano-1.19-pr8这个旧版本的进行了对比后发现的只要这个是第一个就跳转了)。进入函数
在程序返回的地方直接修改是错误的
000000013FE85827 | C6 05 EA C1 19 00 | mov byte ptr ds:,0 |
000000013FE8582E | C6 05 E4 C1 19 00 | mov byte ptr ds:,0 |
000000013FE85835 | 8B C3 | mov eax,ebx |
000000013FE85837 | 4C 8D 9C 24 80 08 | lea r11,qword ptr ss: |
000000013FE8583F | 49 8B 5B 30 | mov rbx,qword ptr ds: |
000000013FE85843 | 49 8B 6B 38 | mov rbp,qword ptr ds: |
000000013FE85847 | 49 8B 73 48 | mov rsi,qword ptr ds: |
000000013FE8584B | 49 8B E3 | mov rsp,r11 |
000000013FE8584E | 41 5F | pop r15 |
000000013FE85850 | 41 5E | pop r14 |
000000013FE85852 | 41 5D | pop r13 |
000000013FE85854 | 41 5C | pop r12 |
000000013FE85856 | 5F | pop rdi |
000000013FE85857 | C3 | ret |
但是旧的krpano-1.19-pr8这个地方明明是eax=1的啊,没有放弃在这个函数里面下断点,对比了旧版本的地方 发现只要这个地方新版本进行了跳转,并且返回了eax=0
000000013FE8567A | 0F 86 8D 01 00 00 | jbe krpanotools64.13FE8580D |
000000013FE85680 | 48 8D 4C 24 20 | lea rcx,qword ptr ss: |
000000013FE85685 | 48 83 7C 24 38 10 | cmp qword ptr ss:,10 |
000000013FE8568B | 48 0F 43 4C 24 20 | cmovae rcx,qword ptr ss: |
000000013FE85691 | E8 32 F6 0C 00 | call krpanotools64.13FF54CC8 |
000000013FE85696 | 8B F8 | mov edi,eax |
000000013FE85698 | FF C8 | dec eax |
000000013FE8569A | 3D FD 00 00 00 | cmp eax,FD |
000000013FE8569F | 0F 87 68 01 00 00 | ja krpanotools64.13FE8580D |
000000013FE856A5 | 48 8D 8C 24 80 00 | lea rcx,qword ptr ss: | :ReadFile+59
000000013FE856AD | E8 BE C6 FF FF | call krpanotools64.13FE81D70 | 新版中修改过的检查秘钥地方
000000013FE856B2 | 84 C0 | test al,al |
000000013FE856B4 | 0F 85 53 01 00 00 | jne krpanotools64.13FE8580D |
000000013FE856BA | 40 F6 C7 01 | test dil,1 |
000000013FE856BE | 0F 84 93 00 00 00 | je krpanotools64.13FE85757 |
000000013FE856C4 | 48 8D 0D 55 C3 19 | lea rcx,qword ptr ds: |
000000013FE856CB | 48 8D 94 24 80 00 | lea rdx,qword ptr ss: | :ReadFile+59
000000013FE856D3 | 41 B8 00 08 00 00 | mov r8d,800 |
000000013FE856D9 | E8 A2 F1 0C 00 | call krpanotools64.13FF54880 |
000000013FE856DE | 45 84 ED | test r13b,r13b |
000000013FE856E1 | 74 20 | je krpanotools64.13FE85703 |
000000013FE856E3 | 48 8B 0D 16 C3 19 | mov rcx,qword ptr ds: |
000000013FE856EA | 48 85 C9 | test rcx,rcx |
000000013FE856ED | 74 05 | je krpanotools64.13FE856F4 |
000000013FE856EF | E8 C0 F4 0C 00 | call krpanotools64.13FF54BB4 |
000000013FE856F4 | 49 8B CC | mov rcx,r12 |
000000013FE856F7 | E8 C0 3A 0D 00 | call krpanotools64.13FF591BC |
修改al的值 发现注册成功了
那说明 call krpanotools64.13FE81D70 这个函数和旧版本的不一样,进入后发现程序跳转到了mov al ,0然后就返回了,通过修改这个地方,程序显示注册成功。
000000013FE85381 | B0 01 | mov al,1 |
注意一下call krpanotools64.13FE81D70 这个函数不能一路按F8 不然程序就会报错,所以我用F9到函数末段 在用回溯的方法,从最后往上找发现了这个关键点。
无聊的时候我再往上还有新发现:
第一发现与旧版本就两个地方发生了跳转导致注册失败,
第1处是:
000000013FE82FA3 | E8 D8 3D 00 00 | call krpanotools64.13FE86D80 |
000000013FE82FA8 | 85 C0 | test eax,eax | eax:"531196943"
000000013FE82FAA | 0F 84 66 0D 00 00 | je krpanotools64.13FE83D16 |
第2处是:
000000013FE83749 | E8 32 36 00 00 | call krpanotools64.13FE86D80 |
000000013FE8374E | 85 C0 | test eax,eax | eax:&"506417225@qq.com"
000000013FE83750 | 0F 84 C0 05 00 00 | je krpanotools64.13FE83D16 |
第二 不修改eax 修改sil = 0也是可以的
000000013FE83D14 | EB 03 | jmp krpanotools64.13FE83D19 |
000000013FE83D16 | 40 B6 01 | mov sil,1 |
000000013FE83D19 | 41 F6 C5 08 | test r13b,8 |
这次可能修改有点难度
事先声明 旧版本的注册码是我网上找来的,如果侵犯了某人的利益,请私信我 我再把这个注册码屏蔽了。
本帖最后由 lelandyang 于 2017-6-11 16:02 编辑
这个程序是使用Enigma打包的,直接解包出来的的页面似乎没有注册算法。直接Crack掉那两个控制台程序比拿下这个打包了的krpano Tools容易多了,那两个控制台都没有加壳。
其次,我猜想这个程序应该是使用的非对称算法加密。应该有一个内置KEY
mmomm 发表于 2017-6-9 17:58
大牛,分享一份破解后的呗
如果你没有用的话 拿去也是没什么用的 我试着使用这个软件 发现还是有门槛的 如果不是专业的人员 拿去也是没有什么用的 大牛,虽然看不懂但是感觉很高端的样子! 收藏收藏。。。。。。。。。。。。。。。。。。。。。。。
大牛,分享一份破解后的呗 本帖最后由 spray 于 2017-6-10 10:14 编辑
很好的教程,支持。
看不懂,来支持一下 一个全景图场景生成器,用它可生成简单(够用)的全景效果了,不过要想玩得好,没些网页编程基础是不行的。当然,你的全景拍摄水平也得好些,高质量的图才是真正的基础。 这个软件只是个内核,要结合专业的GUI软件才好用。感谢分享!
页:
[1]
2