看雪论坛
发新帖

[求助]请问这个漏洞程序为何输入13个H也能绕过验证呢?

wjcabc 2017-2-11 09:35 513
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int valid_serial(char *psz)
{
        size_t len = strlen(psz);
        unsigned total = 0;
        size_t i;
        if(len < 10)
        return 0;
        for(i=0;i<len;i++)
        {
                if((psz[i]<'0') || (psz[i]>'z'))
                return 0;
        total += psz[i];
}
        if(total%853==83)
        return 1;
return 0;
}

int validate_serial()
{
        char serial[24];
        fscanf(stdin, "%s", serial);
        if(valid_serial(serial))
        return 1;
        else
        return 0;
}

int do_valid_stuff()
{
        printf("The serial number is valid!\n"); //do serial-restricted, valid stuff here.
        exit(0);
}
int do_invalid_stuff()
{
        printf("Invalid serial number!\nExiting\n");
        exit(1);
}

int main(int argc, char *argv[])
{
        if(validate_serial())
        do_valid_stuff();
        else
        do_invalid_stuff();
        return 0;
}
除了传统的用跳转地址覆盖EIP的方法,输入13个字母H就能绕过验证,显示The serial number is valid!请教原理
本主题帖已收到 0 次赞赏,累计¥0.00
最新回复 (2)
1
SilentGamb 2017-2-11 12:44
2
#include "stdafx.h"
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

// 13个'H'符合注册码条件,是因为符合注册条件: (注册码长度 >= 10) && ((注册码长度 <= 23)) && (字符累加和 % 0x355 == 0x53)
// 能符合注册条件的注册码很多, 可以做个注册机, 使输入的字符为10个(最短的注册码), 符合(字符累加和 % 0x355 == 0x53)即可

#define REG_SN_CHAR_PRE_LEN 9

int valid_serial(char* psz);
void showRegSnCanUse(char cRegSnPre, int iPreLen, int iAddSumPre);

int validate_serial()
{
    char serial[24];
    fscanf(stdin, "%s", serial);
    
    if (valid_serial(serial)) {
        return 1;
    } else {
        return 0;
    }
}

int do_valid_stuff()
{
    printf("The serial number is valid!\n"); //do serial-restricted, valid stuff here.
    return 0;
}
int do_invalid_stuff()
{
    printf("Invalid serial number!\nExiting\n");
    return 0;
}

int valid_serial(char* psz)
{
    size_t len = strlen(psz);
    unsigned total = 0;
    size_t i;
    int iMod = 0;
    
    if (len < 10) {
        return 0;
    }
    
    for (i = 0; i < len; i++) {
        if ((psz[i] < '0') || (psz[i] > 'z')) {
            return 0;
        }
        
        total += psz[i];
    }
    
    iMod = total % 853/*0x355*/;
    
    if (iMod == 83/*0x53*/) {
        return 1;
    }
    
    return 0;
}

int main(int argc, char* argv[])
{
    char cBegin = '\0';
    char cRegSn = '0';
    DWORD dwSum = 0;
    int i = 0;
    printf("register machine for wjcabc@pediy\r\n");
    printf("reg sn charset :");
    
    while ((cRegSn >= '0') && (cRegSn <= 'z')) {
        printf("%c", cRegSn++);
    }
    
    printf("\r\n");
    /**
    reg sn charset :0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmno
    pqrstuvwxyz
    */
    // 符合要求的字符串, 最少10个字符
    // * 字符串由0~z组成, 算字符的累加和 sum
    // * (sum % 0x355) 为0x53
    // 合规的注册码累加和为(0x355 * N + 0x53)
    // 输入13个H合规, 是作者自己定的, 因为他随便写个字符串, 都可以知道累加和%0x355的值
    // 0[30], z[7a]
    // 先构造出注册码前缀(9个字符), 在后面填填1个字符, 使注册条件(sum%0x53 == 0)成立的3个字符, 可以构造出好多组regsn
    printf("reg sn can use list below:\r\n");
    
    for (cBegin = '0'; cBegin <= 'z'; cBegin++) {
        dwSum = 0;
        
        for (i = 0; i < REG_SN_CHAR_PRE_LEN; i++) {
            dwSum += (DWORD)cBegin;
        }
        
        showRegSnCanUse(cBegin, REG_SN_CHAR_PRE_LEN, (int)dwSum);
    }
    
    printf("\r\n");
    printf("please input reg sn as you see :)\r\n");
    
    if (validate_serial()) {
        do_valid_stuff();
    } else {
        do_invalid_stuff();
    }
    
    system("pause");
    return 0;
}

void showRegSnCanUse(char cRegSnPre, int iPreLen, int iAddSumPre)
{
    int i = 0;
    int j = 0;
    int k = 0;
    int m = 0;
    int iAddSum = 0;
    
    for (i = (int)'a'; i <= (int)'z'; i++) {
        //         for (j = (int)'a'; j <= (int)'z'; j++) {
        //             for (k = (int)'a'; k <= (int)'z'; k++) {
        iAddSum = iAddSumPre + i + j + k;
        
        if ((iAddSum % 0x355) != 0x53) {
            continue;
        }
        
        for (m = 0; m < iPreLen; m++) {
            printf("%c", cRegSnPre);
        }
        
        printf("%c%c%c\r\n", (char)i, (char)j, (char)k);
        //             }
        //         }
    }
}

/** 可用注册码列表, 如果前缀字符长度不是9, 而是8~1, 那可用的注册码就更多.
试验了前缀字符长度为7, 遍历后3个字符, 注册码在控制台窗口多的都打不全

register machine for wjcabc@pediy
reg sn charset :0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmno
pqrstuvwxyz
reg sn can use list below:
[[[[[[[[[u
\\\\\\\\\l
]]]]]]]]]c

  please input reg sn as you see :)
  [[[[[[[[[u
  The serial number is valid!
  请按任意键继续. . .
*/
MOVESP 2017-3-17 21:43
3
是不是黑客攻防系统实战篇中的代码片段
返回



©2000-2017 看雪学院 | Based on Xiuno BBS | 知道创宇带宽支持 | 微信公众号:ikanxue
Time: 0.011, SQL: 9 / 京ICP备10040895号-17