• 从火车票提取完整实名信息

    这里所说的完整的实名信息,包含姓名和身份证号码。从身份证号码可以知道籍贯、出生年月、性别。当然,进入相关数据库后,可以知道的东西就更多了。

    网络上很多地方都在稀里哗啦地泄露着各个中国公民的真实姓名与身份证号码的配套信息,甚至包括相关照片。这个……在这里就不讨论了,就此打住。

    这篇文章想说的是,从火车票中提取完整实名信息是多么的容易。

    1、被隐藏的4位身份证号码

    以前的实名制火车票是不会隐藏身份证号码的,全部打印在票面上。如下图:

    huochepiao1.jpg

    后来,似乎觉得这样显示身份证信息不好,于是就隐去其中的4位。但是,加上了旅客的真实姓名。如下图:

    huochepiao2.jpg

    2、恢复被隐藏的4位

    在这里,我先介绍一下身份证的格式。

    现在的身份证为18位,前6位为地址码,如上图中的370112是山东省历城区。后跟着8位日期码,如上图中的1981****,表明身份证的主人是1981年的某月某日出生的。其中的月和日被“*”隐去。后面的两位是顺序号编码,即00。接着以为性别码,即1。最后的一位是校验码,算法如下:

    S = Ai * Wi, i = 2, ... , 18
    Y = mod(S, 11)
    i: 表示号码字符从右至左包括校验码字符在内的位置序号
    Ai:表示第i位置上的身份证号码字符值
    Wi:表示第i位置上的加权因子
    i: 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
    Wi: 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2 1

    可见被隐藏的4位信息,是身份证持有人的生日中的月份和日期。每年有多少天?最多366天。这下明白我的意思没?也就是说,我们只需要枚举最多366次,就可以将隐藏的信息还原,得到真实的身份证信息。而这366次枚举,还必须满足一个条件——前17位计算得到验证码必须和第18位得到的验证码匹配。

    到了这里,我们还需要考虑另一个问题,在这366次枚举中,匹配的概率是多少?我没有认真计算匹配的概率,但假设得到的验证码的概率为平均分布的情况下,366次尝试得到的可能结果为:366*(1/11)=33.3。

    我们使用下面的程序进行枚举:

    #include <iostream>
    
    using namespace std;
    
    int days[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    int nums[20];
    
    bool verifyID(int nums[])
    {
        int iS = 0;   
        int iW[]={0, 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};   
        int verCode[] = {1, 0, 10, 9, 8, 7, 6, 5, 4, 3, 2};
    
        int i;
    
        for(i=1;i<=17;i++)
        {   
            iS += nums[i]* iW[i];   
        }   
        int iY = iS%11;   
        
    	if(nums[18]==verCode[iY])
    	{
    		return true;
    	}
    	else
    	{
    		return false;
    	}
    }
    
    void printNum(int nums[])
    {
    	int i;
    	for(i=1;i<=17;i++)
    	{
    		printf("%d", nums[i]);
    	}
    	(nums[18]==10)?(printf("X")):(printf("%d",nums[18]));
    	printf("\n");
    }
    
    int main()
    {
    	int i,j;
    	int year,count;
    	char buf[128],buf2[2];
    
    	printf("前六位地区码:");
    	scanf("%s",buf);
    
    	nums[1]=buf[0]-'0';
    	nums[2]=buf[1]-'0';
    	nums[3]=buf[2]-'0';
    	nums[4]=buf[3]-'0';
    	nums[5]=buf[4]-'0';
    	nums[6]=buf[5]-'0';
    
    	printf("年份:"");
    	scanf("%s",buf);
    
    	nums[7]=buf[0]-'0';
    	nums[8]=buf[1]-'0';
    	nums[9]=buf[2]-'0';
    	nums[10]=buf[3]-'0';
    
    	year=nums[7]*1000+nums[8]*100+nums[9]*10+nums[10];
    	if(year%400==0 || (year%400!=0 && year%4==0))//闰¨¨°年¨o
    	{
    		days[2]=29;
    	}
    	else
    	{
    		days[2]=28;
    	}
    
    	printf("最后四位:");
    	scanf("%s",buf);
    
    	nums[15]=buf[0]-'0';
    	nums[16]=buf[1]-'0';
    	nums[17]=buf[2]-'0';
    	nums[18]=(buf[3]=='x' || buf[4]=='X')?10:(buf[3]-'0');
    
    	count=0;
    	for(i=1;i<=12;i++)
    	{
    		for(j=1;j<=days[i];j++)
    		{
    			nums[11]=i/10;
    			nums[12]=i%10;
    			nums[13]=j/10;
    			nums[14]=j%10;
    
    			if(verifyID(nums))
    			{
    				printNum(nums);
    				count++;
    			}
    		}
    	}
    
    	printf("共%d个结果\n", count);
    
    	//system("pause");
    
    	return 0;
    }

    运行结果如下:

    前六位地区码:370112

    年份:1981

    最后四位:0010

    70112198101020010

    70112198101100010

    70112198101290010

    70112198102090010

    70112198102170010

    70112198102250010

    70112198103050010

    70112198103130010

    70112198103210010

    70112198104010010

    70112198104280010

    70112198105080010

    70112198105160010

    70112198105240010

    70112198106040010

    70112198106120010

    70112198106200010

    70112198107190010

    70112198107270010

    70112198108070010

    70112198108150010

    70112198108230010

    70112198108310010

    70112198109030010

    70112198109110010

    70112198110090010

    70112198110170010

    70112198110250010

    70112198111050010

    70112198111130010

    70112198111210010

    70112198112010010

    70112198112280010

    共33个结果

    3、更方便得到身份证号码的方法

    以下面的车票为例。

    huochepiao_3.jpg

    车票上的身份证号码部分的信息被PS了很多哦。

    但是,我们扫描一下右边的二维码,得到:

    480176011454143443488249648788273804579014484911756460444584907044800460033197910200023053897628805389762880538976288053897628805389762880820000

    是的,里面的某部分内容就是被PS被“*”掉的身份证号码。

    4、批量高技术方案

    12306,不解释。

    5、总结

    个人别凑热闹晒车票,晒前也拜托好好打个马赛克,重分打个马赛克。还有,某些垄断组织好歹加强一下安全措施。

    本文点到即止,仅作学习交流用途。

    不多说了,就这些。