1. 开篇:当滑块遇上国密,一次完整的登录逆向之旅
大家好,我是老张,在爬虫和安全研究这个圈子里摸爬滚打了十来年,见过各种各样的验证和加密。最近几年,国密算法(SM2、SM3、SM4等)在政务、金融这些对安全要求极高的场景里用得越来越普遍,很多朋友一看到这个就头疼,觉得比常见的AES、RSA要复杂神秘得多。今天,我就拿一个非常典型的、集成了滑块验证和全套国密算法的Web登录系统作为实战案例,带大家从头到尾“拆解”一遍。咱们的目标很明确:不光要弄明白它每一步在干什么,还要亲手写出能自动化完成登录的脚本。这个过程就像侦探破案,一步步追踪线索,最终还原出完整的作案手法。你会发现,只要理清了逻辑,国密算法实战并没有想象中那么难。
这个案例来源于一个真实的政务服务网站,它的登录流程堪称“教科书级”的防御:先来个滑块验证码拦住机器,接着用SM2非对称加密协商密钥,然后用SM4对称加密保护你的账号密码,全程再用HMacSHA256做消息认证确保数据没被篡改。听起来是不是层层设卡?别慌,咱们一层层剥开它的外壳。我会用最直白的话,把SM2、SM4、HMacSHA256在这些环节里扮演的角色讲清楚,并且给出每一步可操作的代码。无论你是想学习国密算法逆向的安全爱好者,还是需要搞定这类登录的爬虫工程师,这篇内容都能给你一条清晰的路径。
2. 初探战场:网络请求中的五个关键“哨卡”
动手逆向之前,咱们得先看看对手的布防。打开浏览器无痕窗口,访问目标登录页,随便输入账号密码点击登录,然后手动完成那个滑块验证。这时候,打开开发者工具的Network面板,你会发现页面在后台默默地发起了一系列请求。别被数量吓到,咱们重点关注其中五个,它们就是登录流程的核心“哨卡”。
第一个哨卡:getPublicKey(获取公钥)。这个请求通常是最先发起的。它的载荷里,你会看到一个叫signature的参数是加密的,但其他部分可能是明文。查看它的响应,核心是返回一个uuid和一个publicKey。这个uuid就像本次会话的身份证号,后续所有请求都会带着它;而publicKey就是SM2算法的公钥,用于后续的加密通信初始化。所以,这个接口的使命就是“握手打招呼”,为后续的加密对话准备好基础材料。
第二个哨卡:sendSm4(发送SM4密钥信息)。紧接着,第二个请求就来了。它的载荷里,signature依然加密,同时多了一个datagram参数,里面包含了刚才拿到的uuid,以及一个加密生成的secret。此外,请求头X-TEMP-INFO也被设置成了那个uuid。这个secret是干嘛的呢?它是后续SM4加密要用到的关键密钥信息,但它是被服务器的公钥(publicKey)加密过的,只有服务器用自己的私钥才能解开。这一步完成了密钥的安全传递。
第三个哨卡:getCaptcha(获取验证码)。轮到滑块验证码登场了。这个请求的datagram和signature也都是加密的。响应里会返回滑块拼图和背景图的两张Base64图片数据,以及一个本次验证码的uuid。我们的脚本需要识别出滑块的滑动距离。
第四个哨卡:verifyCaptcha(验证滑块)。识别出滑动距离后,我们将这个距离值和图片的uuid作为参数,发起验证请求。同样,参数被加密。如果滑动正确,服务器会返回一个加密的datagram,解密后里面包含一个宝贵的ticket(票据)。这个ticket是登录许可的关键凭证。
第五个哨卡:accountLogin(账号登录)。这是最后一步。我们将账号、密码、以及之前获得的ticket等信息,通过加密的方式提交。服务器验证通过后,登录才算真正成功。
理清这五个请求的顺序和依赖关系至关重要。它们环环相扣,getPublicKey是起点,产生的uuid和publicKey贯穿始终;sendSm4传递了加密的会话密钥;getCaptcha和verifyCaptcha处理了人机验证;最后accountLogin完成身份认证。任何一个环节出错,流程都会中断。
3. 逆向核心:定位加密函数与参数构造逻辑
知道了流程,接下来就是最关键的环节——找到加密是怎么发生的。我们回到浏览器,打开开发者工具的Sources面板,或者直接全局搜索关键参数名,比如signature、datagram、encryptCode。
通常,前端会有一个统一的请求拦截器或封装函数来处理加密。搜索signature,你可能会找到类似下面的代码逻辑:
if ("post" === n.method) {
if (S.includes(n.url)) {
o["encryptCode"] = "0";
o.datagram = JSON.stringify(n.data);
} else {
c = JSON.stringify(n.data);
u = Object(P["d"])(c, Object(P["i"])(l));
o.datagram = u;
o["encryptCode"] = "2";
}
// ... 计算 signature ...
}
这段代码透露了两个重要信息:第一,有一个白名单列表S,里面的接口请求(比如getPublicKey和sendSm4)是不加密的(encryptCode为0),datagram直接是数据的JSON字符串。第二,非白名单的请求(如登录、验证码),datagram会经过Object(P["d"])和Object(P["i"])这两个函数处理,且encryptCode变为2。这基本就锁定了加密发生的位置。
接下来,我们逐个分析关键参数的生成:
signature(签名):它的作用是防止数据被篡改。通过跟栈或搜索HMacSHA256,你会发现它的生成方式类似这样:
signature = HmacSHA256(zipCode + encryptCode + u +


1761

被折叠的 条评论
为什么被折叠?



