非HTTP验证码别乱捅!一不小心就反爬了。

admin 2024年8月5日09:06:36评论6 views字数 4092阅读13分38秒阅读模式
大家好,我是TheWeiJun,欢迎来到我的公众号。由于工作太忙,已经有三个月没有发文了,感谢大家的耐心等待和支持。本文将探讨如何逆向某网站的非HTTP验证码,介绍相关技术和工具,并提供详细步骤和示例代码,帮助大家理解和掌握非HTTP验证码的逆向方法。希望这篇文章能为大家带来有价值的知识和实用技巧,也欢迎大家持续关注和交流,一起学习进步!
特别声明:本公众号文章只作为学术研究,不作为其他不法用途;如有侵权请联系作者删除。

每月看好文

目录


一、前言介绍
二、网站分析
三、逆向分析
四、算法还原
五、文章结语
非HTTP验证码别乱捅!一不小心就反爬了。



一、前言介绍

大家有没有想过,每次在网上注册账号或者登录时,那些不使用滑块验证码,也不依赖HTTP协议的验证码是如何识别我们是人而不是机器的呢?这些验证码可能只需要你简单地进行识别操作,例如输入一些文字或数字。但你可曾想过,这些看似简单的验证背后,蕴含着怎样的科技奥秘?在本文中,我们将揭开非HTTP验证码的神秘面纱,一起探索它的工作原理,了解它是如何巧妙地识别真人身份的。在这个有趣的旅程中,我们将一窥技术背后的精妙,带你进入一个充满挑战和创新的数字世界。快来和我一起探索吧!


二、网站分析

1、从某APP中抓包分析用户登录接口,发现登录接口为webview,将登录接口url使用浏览器打开分析,截图如下:

非HTTP验证码别乱捅!一不小心就反爬了。

2、打开浏览器开发者工具,然后输入手机号后,点击发送验证码,请求截图如下所示:

非HTTP验证码别乱捅!一不小心就反爬了。

3、浏览器Network中查看请求包,我们并没有发现http请求接口的验证码,只发现了疑似验证码的请求体和响应体,截图如下:

非HTTP验证码别乱捅!一不小心就反爬了。

非HTTP验证码别乱捅!一不小心就反爬了。

总结:此处我们发现response的返回内容进行了加密,加密参数为encrypt_body。我们再分析下request请求体,结果发现加密参数也是encrypt_body。这里我们初步可以确定,请求入参和response出参使用的是一套加密算法,接下来我们进入逆向分析环节吧。


三、逆向分析

1、通过Initiator进行调试分析,过滤无限debugger模式,进行断点分析截图如下所示:

非HTTP验证码别乱捅!一不小心就反爬了。

2、这里我们定位到了请求体加密前参数,先暂时忽略。我们紧接着往下继续分析,截图如下:

非HTTP验证码别乱捅!一不小心就反爬了。

3、此处我们查看返回参数s,可以确定是请求体加密后的参数,截图如下:

非HTTP验证码别乱捅!一不小心就反爬了。

总结:虽然前面简单分析过,请求体和响应体的encrypt_body使用的是一套加密算法。那么我们先还原请求体加密,再拿请求体加密的对称加密算法进行解密,就可以判断我们前面的猜测是否正确。通过断点分析我们发现请求体加密使用了aes-ecb模式,AES是一种对称加密算法,这意味着加密和解密使用相同的密钥。接下来我们进入算法还原环节,来验证下我们的猜测吧。


四、算法还原

1、使用Python还原JS加密算法,还原后的完整加密算法如下:

# -*- coding: utf-8 -*-# -------------------------------# @author : TheWeiJUn# @time   : 2024.08.04 20:58:33# -------------------------------

from Crypto.Cipher import AESimport jsonimport base64

from Crypto.Util.Padding import pad



def encrypt(e, n):    if e and n:        if not isinstance(e, str):            e = json.dumps(e, separators=(",", ":"))

        r = 'utf-8'

        key = n.encode(r)  # Assuming n is a string that needs to be encoded to bytes        data = e.encode(r)

        cipher = AES.new(key, AES.MODE_ECB)        padded_data = pad(data, AES.block_size)  # Pad the data to be a multiple of block size        cipher_text = cipher.encrypt(padded_data)  # Encrypt the padded data

        s = base64.b64encode(cipher_text).decode('utf-8')        return s



if __name__ == '__main__':    # Example usage:    e = {"phone": "xxxx", "countryCode": "CN", "type": "login"}    n = "1234567890123456"  # Example key (must be 16 bytes for AES-128)    result = encrypt(e, n)    print(result)

2、输出Python加密后的参数s同浏览器中生成的加密参数s进行比对,截图如下:

非HTTP验证码别乱捅!一不小心就反爬了。

非HTTP验证码别乱捅!一不小心就反爬了。

总结:经过对比我们发现,两个参数字符串完全一致。接下来我们使用前面分析的方法对response加密体参数encrypt_body试着进行对称解密还原。截图如下所示:

非HTTP验证码别乱捅!一不小心就反爬了。

3、解密还原失败,此处我怀疑response加密参数encrypt_body应该是做了特殊处理,经过断点分析后,果真如我所言,编辑修改后的decrypt解密代码如下:

# -*- coding: utf-8 -*-# -------------------------------# @author : TheWeiJUn# @time   : 2024.08.04 20:58:33# -------------------------------

from Crypto.Cipher import AESimport jsonimport base64

from Crypto.Util.Padding import pad, unpad



def encrypt(e, n):    if e and n:        if not isinstance(e, str):            e = json.dumps(e, separators=(",", ":"))

        r = 'utf-8'

        key = n.encode(r)  # Assuming n is a string that needs to be encoded to bytes        data = e.encode(r)

        cipher = AES.new(key, AES.MODE_ECB)        padded_data = pad(data, AES.block_size)  # Pad the data to be a multiple of block size        cipher_text = cipher.encrypt(padded_data)  # Encrypt the padded data

        s = base64.b64encode(cipher_text).decode('utf-8')        return s



def decode_base64(t):    # Add padding to make the length a multiple of 4    t = t + '=' * (4 - len(t) % 4)

    # Replace URL-safe characters with standard Base64 characters    t = t.replace('-', '+').replace('_', '/')

    # Decode the Base64 string    return base64.b64decode(t)



def decrypt(e, n):    if e and n:        # Decode the Base64 encoded input        cipher_text_bytes = decode_base64(e)        # Define the encoding and decoding formats        a = 'utf-8'        key = n.encode(a)  # Convert key to bytes

        # Create the cipher object for decryption        cipher = AES.new(key, AES.MODE_ECB)        padded_data = cipher.decrypt(cipher_text_bytes)  # Decrypt the data        # Remove padding        data = unpad(padded_data, AES.block_size)        # Parse the JSON data        return json.loads(data.decode(a))



if __name__ == '__main__':    n = "1234567890123456"  # Example key (must be 16 bytes for AES-128)    e = "encrypt_body"    result = decrypt(e, n)    print(result)

4、对加密参数进行padding填充及对特殊符号进行替换处理后,即可进行对称解密操作,解码后的截图如下所示:

非HTTP验证码别乱捅!一不小心就反爬了。

5、对还原后的响应体graph参数进行特殊处理后,进行base64decode,相关代码和解码后保存的字节流如下:

非HTTP验证码别乱捅!一不小心就反爬了。

非HTTP验证码别乱捅!一不小心就反爬了。

6、到这里基本就结束了,接下来进行验证码识别还原,这个相对来说比较简单,我们这里使用ddddocr,编辑代码后还原验证码如下所示:

非HTTP验证码别乱捅!一不小心就反爬了。


五、文章结语

本篇分享到这里就结束了,感谢大家的阅读和支持。如果你对爬虫逆向分析、验证码破解及其他技术话题感兴趣,记得关注我的公众号,不错过下一期的更新。我们将继续深入探讨各种技术细节和实用技巧,一起探索数字世界的奥秘。期待与你在下期文章中再见,一起学习,一起进步!☀️☀️✌️

往期推荐
Scrapy结合MongoDB源码重构,打磨完美指纹存储机制!
用Scrapy爬取5秒盾站点,结果万万没想到,速度可以这么快!
某云滑块验证码别乱捅!一不小心就反爬了。
某美滑块验证码别乱捅!一不小心就反爬了。
深入探索Go语言net/http包源码:从爬虫的视角解析HTTP客户端

非HTTP验证码别乱捅!一不小心就反爬了。

如果想要获得更多精彩内容可以关注我朋友:


非HTTP验证码别乱捅!一不小心就反爬了。

END

非HTTP验证码别乱捅!一不小心就反爬了。

作者简介
我是TheWeiJun有着执着的追求,信奉终身成长,不定义自己,热爱技术但不拘泥于技术,爱好分享,喜欢读书和乐于结交朋友,欢迎扫我微信与我交朋友💕
分享日常学习中关于爬虫及逆向分析的一些思路,文中若有错误的地方,欢迎大家多多交流指正💕
非HTTP验证码别乱捅!一不小心就反爬了。

非HTTP验证码别乱捅!一不小心就反爬了。

点分享

非HTTP验证码别乱捅!一不小心就反爬了。

点收藏

非HTTP验证码别乱捅!一不小心就反爬了。

点点赞

非HTTP验证码别乱捅!一不小心就反爬了。

点在看

原文始发于微信公众号(逆向与爬虫的故事):非HTTP验证码别乱捅!一不小心就反爬了。

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年8月5日09:06:36
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   非HTTP验证码别乱捅!一不小心就反爬了。http://cn-sec.com/archives/3035936.html

发表评论

匿名网友 填写信息