首页
社区
课程
招聘
[原创]一时兴起分析并绕过某网站验证码验证
发表于: 2025-11-9 16:44 2873

[原创]一时兴起分析并绕过某网站验证码验证

2025-11-9 16:44
2873

先赞一个:前段时间偶然刷到这个网站(d59K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6^5K9h3q4G2L8r3W2F1j5$3!0V1K9h3&6Y4i4K6u0W2j5$3!0E0i4K6u0r3i4K6t1&6i4@1g2r3i4@1u0o6i4K6S2o6i4@1f1&6i4K6R3%4i4K6S2o6i4@1f1&6i4K6W2p5i4@1p5J5i4@1f1$3i4K6W2o6i4K6R3&6i4@1f1#2i4@1u0q4i4K6R3^5i4@1f1#2i4@1p5@1i4K6W2m8i4@1f1@1i4@1u0o6i4K6V1^5i4@1f1^5i4@1t1@1i4@1p5^5i4@1f1#2i4K6R3$3i4K6R3#2i4@1f1#2i4@1q4q4i4@1t1&6i4@1g2r3i4@1u0o6i4K6S2o6i4@1f1$3i4K6R3^5i4K6V1I4i4@1f1#2i4K6S2r3i4@1q4m8i4@1f1%4i4K6W2o6i4K6S2n7i4@1f1^5i4@1u0r3i4K6R3%4i4@1f1#2i4K6W2n7i4@1u0q4i4@1f1^5i4@1p5%4i4@1p5K6i4@1f1%4i4@1t1K6i4@1u0n7i4@1f1%4i4@1u0n7i4K6W2r3i4@1f1%4i4@1t1K6i4@1u0n7i4@1f1#2i4K6R3^5i4K6V1%4i4@1f1%4i4K6W2m8i4K6R3@1i4@1f1&6i4K6R3K6i4@1p5^5i4@1f1#2i4K6R3^5i4K6R3$3i4@1f1%4i4@1q4n7i4@1p5H3i4@1f1^5i4K6S2m8i4K6R3J5i4@1g2r3i4@1u0o6i4K6S2o6i4@1f1@1i4@1t1^5i4@1q4m8i4@1f1@1i4@1u0m8i4@1u0m8i4@1f1^5i4@1p5%4i4K6R3&6i4@1f1#2i4@1u0q4i4K6V1%4i4@1f1^5i4@1q4q4i4@1t1J5i4@1f1^5i4@1p5%4i4@1p5K6i4@1f1#2i4@1u0q4i4K6V1%4i4@1f1&6i4K6W2p5i4K6W2q4i4@1f1#2i4@1t1^5i4@1t1^5i4@1f1#2i4@1p5#2i4@1u0p5i4@1g2r3i4@1u0o6i4K6S2o6i4@1f1@1i4@1t1^5i4K6R3H3i4@1f1#2i4K6W2n7i4@1u0q4i4@1f1^5i4K6R3K6i4K6W2o6i4@1f1#2i4K6S2p5i4K6R3K6i4@1f1^5i4@1p5^5i4K6R3H3i4@1g2r3i4@1u0o6i4K6S2o6i4@1f1%4i4K6V1@1i4@1p5^5i4@1f1#2i4K6W2n7i4@1u0q4i4@1f1^5i4@1p5%4i4@1p5K6i4@1f1%4i4K6W2m8i4K6R3@1i4@1f1$3i4K6V1$3i4@1t1&6i4@1f1#2i4@1u0o6i4K6S2r3i4@1f1^5i4@1q4q4i4@1t1J5i4@1f1^5i4@1p5%4i4@1p5K6i4@1f1%4i4K6W2r3i4@1p5#2i4@1f1^5i4@1q4r3i4K6R3$3i4@1f1$3i4@1t1%4i4@1t1I4i4@1f1#2i4@1u0q4i4K6V1%4i4@1f1$3i4K6R3^5i4K6V1I4i4@1f1%4i4K6W2m8i4K6R3@1i4@1f1#2i4K6V1$3i4K6W2o6i4@1f1$3i4@1q4o6i4@1p5J5i4@1f1K6i4K6R3H3i4K6R3J5

昨天晚上又随手点开这个网站,随便看看,结果发现阅读全文又需要输入验证码,看来又过期了。其实我早就已经关注过公众号了,验证码可以在公众号里免费获取。但是此时我不想打开公众号去重新获取,因为内心感觉这个验证应该挺简单的,于是了绕过它的冲动。

由于我只有html、css、js的基础语法知识(很久没复习也忘得差不多了),平时也没做过web相关的逆向分析,连开发也没做过,工作也没用到过这些知识技能,所以一时兴起的我只能连猜带蒙,现学现卖,记录下此次的探索过程。

在网页中按F12这个我倒是知道的,查看请求和响应,在响应中可以看到,全文内容其实已经拿到了,只是没有显示出来:

那么首先想的就是能否直接去除遮挡,当场搜索并写了一下代码,在控制台中尝试运行:

运行之后,看到网页有变化,稍微兴奋了一下,但是并没有显示出全文内容,而是把一些隐藏的元素显示出来了:

接着猜想,应该是js代码控制的显示逻辑的,那就去看看js代码。
先随便输入一个验证码,会弹出错误提示:

这个框不就是alert函数弹出来的么,这点知识我还是有的。
在源代码这里查看js代码,只在app这个js中搜到了alert相关的代码,全部打上断点。但是运行发现,点击【提交】按钮后并没有中断:

【注】:这是第一次与成功失之交臂,由于当时没有仔细观察,上图左下角提示弹窗验证是由TechGrow提供,那么在源代码中就应该去qiniu.techgrow.co里看js代码,而不是xiaolincoding.com。

那么只能再转换思路了,找验证码的【提交】按钮在哪里,经过了几次尝试没找到,后来才发现,可以直接在【提交】按钮这里右键检查,直接就能定位。。。

接下来就是找【提交】按钮对应的处理函数,但是浏览上图代码,并没有在按钮附近找到调用了什么函数。
那么又得现学了,经过搜索学习,原来在F12窗口中有【事件监听器】这个东西,在click里面找到了【提交】按钮以及对应的js代码为readmore.js:

点开readmore.js,好家伙,原来在qiniu.techgrow.cn里,刚刚看错了,不应该看xiaolincoding.com:

大致浏览了一下readmore.js代码,很明显加了混淆:

先搜索错误弹窗的文本和alert吧,"验证码无效"没有搜到,而alert有,又又又开始兴奋了。

给alert所在行全部打上断点,然后随便输入验证码,点击按钮后并没有断下,咦?咋回事?

【注】:这是第二次与成功失之交臂,弹窗确实是由alert触发的,如果在第一个断点的上一行再下断,就能触发中断,可惜当时没有想到。

难道不是走的alert吗?于是我又开始搜索学习了,搜索弹窗的方式有哪些,但是都不对:

没有找到弹窗的地方,那就只有去分析readmore.js代码的逻辑了。由于加了混淆,所以直接搜索在线的去混淆工具,用了好几个,只有d60K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6G2j5X3k6Q4x3X3c8A6L8#2)9J5k6h3c8W2L8$3u0X3N6i4y4U0j5i4c8W2i4K6u0W2K9h3!0Q4x3V1k6Q4c8e0k6Q4z5e0g2Q4z5o6S2Q4c8e0k6Q4z5f1g2Q4z5f1y4Q4c8e0k6Q4z5f1y4Q4z5o6m8Q4c8e0g2Q4b7e0g2Q4b7V1c8Q4c8f1k6Q4b7V1y4Q4z5p5y4Q4c8e0N6Q4z5f1u0Q4b7U0c8Q4c8e0k6Q4z5p5g2Q4b7e0g2Q4c8e0S2Q4b7e0N6Q4b7e0y4Q4c8e0g2Q4z5o6N6Q4b7V1q4Q4c8e0c8Q4b7V1q4Q4z5o6j5`."验证码无效"等明文:

OK开始分析源码,"验证码无效"直接定位到了关键函数,分析如下:

逻辑一目了然,用POST请求ee4K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6G2M7r3g2F1i4K6u0W2N6r3g2U0K9r3N6J5L8%4N6Q4x3X3g2U0L8W2)9J5c8X3q4H3K9g2)9J5c8Y4u0W2j5h3c8E0L8%4u0W2i4K6u0r3j5$3q4H3N6r3y4Z5j5g2)9J5c8Y4k6S2L8r3W2V1j5i4c8W2i4@1f1#2i4K6W2r3i4K6W2r3i4@1f1#2i4K6V1H3i4K6S2p5i4@1f1#2i4K6R3I4i4K6W2m8i4@1f1%4i4K6W2m8i4K6R3@1i4@1f1&6i4@1q4m8i4K6S2o6i4@1f1^5i4@1q4r3i4K6R3I4i4@1f1%4i4@1p5H3i4K6R3I4i4@1f1$3i4@1p5H3i4@1p5I4i4@1f1&6i4@1q4m8i4K6S2o6i4@1f1K6i4K6R3H3i4K6R3J5
如果请求成功,响应的状态码是0x196(十进制406),就会弹窗提示"验证码无效":

如果响应状态码为0,就会保存token,并调用_0x9dd5f2(0x3)函数:

_0x9dd5f2函数分析如下,主要做的就是存储token及有效期、显示全文内容:

经过前面的分析,根据在其他领域的逆向经验,直接能想到的两种绕过方法:
1、在验证函数_0x265c84()内部的success处下断,修改响应状态码,将406改为0,强制走成功分支。
但是并没有成功:

2、直接调用_0x9dd5f2(0x3)函数,OK NO趴笨,全文可看了,搞定:

这个验证难度不大,适合新手。同时也记录了自己在不熟的领域,因为一时兴起和好奇,边实践边猜测边学习,达到了自己想要的目标的过程。

// 修改CSS显示属性
 
// 显示所有隐藏的元素
document.querySelectorAll('[style*="display: none"]').forEach(el => {
    el.style.display = 'block';
});
 
// 移除hidden类
document.querySelectorAll('.hidden').forEach(el => {
    el.classList.remove('hidden');
});
 
// 更暴力的方法:显示所有元素
document.querySelectorAll('*').forEach(el => {
    el.style.display = 'block';
    el.style.visibility = 'visible';
});
// 修改CSS显示属性
 
// 显示所有隐藏的元素
document.querySelectorAll('[style*="display: none"]').forEach(el => {
    el.style.display = 'block';
});
 
// 移除hidden类
document.querySelectorAll('.hidden').forEach(el => {
    el.classList.remove('hidden');
});
 
// 更暴力的方法:显示所有元素
document.querySelectorAll('*').forEach(el => {
    el.style.display = 'block';
    el.style.visibility = 'visible';
});
● confirm():带 “确定” 和 “取消” 按钮的弹窗。
  不是这个,因为网页的弹窗没有"取消"按钮
● prompt():带输入框的弹窗,可让用户输入内容,返回输入的字符串(取消则返回null)。
  不是这个,网页只是单纯弹窗,没有让输入什么内容
● 自定义弹窗:实际开发中常使用自定义HTML+CSS弹窗,可控制位置(如顶部)、样式和动画。
  难道是这个?这么高级?算了,不去分析是不是自定义弹窗了,麻烦。
● confirm():带 “确定” 和 “取消” 按钮的弹窗。
  不是这个,因为网页的弹窗没有"取消"按钮
● prompt():带输入框的弹窗,可让用户输入内容,返回输入的字符串(取消则返回null)。
  不是这个,网页只是单纯弹窗,没有让输入什么内容
● 自定义弹窗:实际开发中常使用自定义HTML+CSS弹窗,可控制位置(如顶部)、样式和动画。
  难道是这个?这么高级?算了,不去分析是不是自定义弹窗了,麻烦。
// 验证验证码函数
function _0x265c84() {
  // 获取输入框中用户输入的验证码值(通过jQuery选择器定位输入框)
  var _0x350b2c = jQuery("#readmore-modal-captcha-input").val();
  // 判断验证码是否存在且不为空(去除首尾空格后仍非空)
  if (_0x350b2c && '' !== jQuery.trim(_0x350b2c)) {
    // 发起AJAX请求验证验证码
    jQuery.ajax({
      // 请求URL:如果基础URL不存在或为空,则使用默认URL,否则拼接基础URL和接口路径
      'url': null == _0x4100eb.baseUrl || '' === jQuery.trim(_0x4100eb.baseUrl) ? "d54K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6G2M7r3g2F1i4K6u0W2N6r3g2U0K9r3N6J5L8%4N6Q4x3X3g2U0L8W2)9J5c8X3q4H3K9g2)9J5c8Y4u0W2j5h3c8E0L8%4u0W2i4K6u0r3j5$3q4H3N6r3y4Z5j5g2)9J5c8Y4k6S2L8r3W2V1j5i4c8W2" : _0x4100eb.baseUrl + "/api/readmore/captcha/validate",
      // 请求方法为POST
      'method': 'POST',
      // 预期响应数据类型为JSON
      'datatype': "json",
      // 请求内容类型为JSON
      'contentType': "application/json",
      // 请求数据:将验证码和博客ID转换为JSON字符串(博客ID可选,为空则传空字符串)
      'data': JSON.stringify({
        'code': _0x350b2c,
        'blogId': _0x4100eb.blogId || ''
      }),
      // 请求成功的回调函数(参数_0x4d35b7为服务器返回的响应数据)
      'success': function (_0x4d35b7) {
        // 若响应状态码为0(成功)
        if (0x0 === _0x4d35b7.code) {
          // 保存服务器返回的token到变量_0x19a4fa
          _0x19a4fa = _0x4d35b7.data.token;
          // 调用函数_0x9dd5f2,传入参数3(验证成功后的后续操作,如显示更多内容)
          _0x9dd5f2(0x3);
        }
        // 若响应状态码为4060x196十六进制转十进制为406),提示验证码无效
        else if (0x196 === _0x4d35b7.code) {
          alert("验证码无效");
        }
        // 若响应状态码为4070x197转十进制为407),提示博客ID无效
        else if (0x197 === _0x4d35b7.code) {
          alert("博客ID无效");
        }
        // 若响应状态码为5000x1f4转十进制为500),提示服务器出错
        else if (0x1f4 === _0x4d35b7.code) {
          alert("服务器出错, 请稍后再试");
        }
        // 若响应状态码为5020x1f6转十进制为502),提示非法参数
        else if (0x1f6 === _0x4d35b7.code) {
          alert("非法参数传递");
        }
      },
      // 请求失败的回调函数(参数分别为XMLHttpRequest对象、错误状态、错误信息)
      'error': function (_0x5a87eb, _0x31c697, _0x53ba39) {
        // 若HTTP状态码为4030x193转十进制为403),提示非法请求来源
        if (0x193 === _0x5a87eb.status) {
          alert("非法请求来源");
        }
        // 若HTTP状态码为4290x1ad转十进制为429),提示操作频繁
        else if (0x1ad === _0x5a87eb.status) {
          alert("操作过于频繁, 请稍后再试");
        }
        // 若HTTP状态码为500,提示服务器出错
        else if (0x1f4 === _0x5a87eb.status) {
          alert("服务器出错, 请稍后再试");
        }
        // 其他错误状态,提示网络或服务器连接失败
        else {
          alert("网络或服务器连接失败, 请稍后再试");
        }
      }
    });
  }
}
// 验证验证码函数
function _0x265c84() {
  // 获取输入框中用户输入的验证码值(通过jQuery选择器定位输入框)
  var _0x350b2c = jQuery("#readmore-modal-captcha-input").val();
  // 判断验证码是否存在且不为空(去除首尾空格后仍非空)
  if (_0x350b2c && '' !== jQuery.trim(_0x350b2c)) {
    // 发起AJAX请求验证验证码
    jQuery.ajax({
      // 请求URL:如果基础URL不存在或为空,则使用默认URL,否则拼接基础URL和接口路径
      'url': null == _0x4100eb.baseUrl || '' === jQuery.trim(_0x4100eb.baseUrl) ? "a79K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6G2M7r3g2F1i4K6u0W2N6r3g2U0K9r3N6J5L8%4N6Q4x3X3g2U0L8W2)9J5c8X3q4H3K9g2)9J5c8Y4u0W2j5h3c8E0L8%4u0W2i4K6u0r3j5$3q4H3N6r3y4Z5j5g2)9J5c8Y4k6S2L8r3W2V1j5i4c8W2" : _0x4100eb.baseUrl + "/api/readmore/captcha/validate",
      // 请求方法为POST
      'method': 'POST',
      // 预期响应数据类型为JSON
      'datatype': "json",
      // 请求内容类型为JSON
      'contentType': "application/json",
      // 请求数据:将验证码和博客ID转换为JSON字符串(博客ID可选,为空则传空字符串)
      'data': JSON.stringify({
        'code': _0x350b2c,
        'blogId': _0x4100eb.blogId || ''
      }),
      // 请求成功的回调函数(参数_0x4d35b7为服务器返回的响应数据)
      'success': function (_0x4d35b7) {
        // 若响应状态码为0(成功)
        if (0x0 === _0x4d35b7.code) {
          // 保存服务器返回的token到变量_0x19a4fa
          _0x19a4fa = _0x4d35b7.data.token;
          // 调用函数_0x9dd5f2,传入参数3(验证成功后的后续操作,如显示更多内容)
          _0x9dd5f2(0x3);
        }
        // 若响应状态码为4060x196十六进制转十进制为406),提示验证码无效
        else if (0x196 === _0x4d35b7.code) {
          alert("验证码无效");
        }

[培训]Windows内核深度攻防:从Hook技术到Rootkit实战!

收藏
免费 2
支持
分享
最新回复 (1)
雪    币: 966
活跃值: (2730)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
我发现有个更简单的方法,直接在当前页面设置禁用js就可以看完整版内容,不需要任何操作
2025-12-16 10:53
0
游客
登录 | 注册 方可回帖
返回