Linux工具开发[02]---编程实现对输入字符序列变换(编码/加密/散列)方式的智能判定

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux工具开发[02]---编程实现对输入字符序列变换(编码/加密/散列)方式的智能判定相关的知识,希望对你有一定的参考价值。

怎样简单实现一个能够智能判定输入字符序列变换方式的小程序

本文由CSDN-蚍蜉撼青松 【主页:http://blog.csdn.net/howeverpf】原创,转载请注明出处!

问题描写叙述:

        在分析网络数据包或者研究安全问题时。经常会遇到变换后的字符序列。而是否能准确识别密文的变换算法,对进一步的分析工作非常关键。

经常使用的变换算法包含但不限于:Base64、URL编码、html编码、MD5散列、DES加密、RSA加密等。

要求:

  1)在理解算法原理及密文特点的基础上。使用随意编程语言实现,当输入一段密文时,返回可能的变换算法。
  2)能准确识别5种以上变换或加密算法。


实现思路:

        选择用来识别的变换算法包含:URL编码、QP(全称Quoted-Printable)编码、Unicode编码、HTML特殊实体编码、Base64编码、MD5散列、SHA1散列。

        首先分析这七种变换算法的特点。分别提出判别根据与函数实现:

  • URL编码的特点是在百分号’%’紧跟两个十六进制数(大写和小写皆可),因此我们须要在输入字节流中找到’%’所处的位置,判定其后两个字符是否为十六进制值。

    若有符合此条件的。则能够大概判定使用了URL编码。若全都不符合,则不可能使用了URL编码。

    -----存在型判定

URL编码判定函数实现例如以下

// 判定是否存在URL编码
//參数 pszBuff,   待判定字符序列
//返回 若一切正常,返回 true
bool IsEncodedbyURL(char *pszBuff)
{
    int i,j;

    // 百分号 数量上是否正常
    if (g_nCountPC == ARRAY_MAX_SIZE)
        DbgMsgPrint("Please make the buffer size bigger for ‘%‘.");
    else if (g_nCountPC == 0)
        return true;

    // 百分号 数量正常的话, 遍历待判定字符序列中全部的百分号【已由预处理的时候取得】
    //若每一个百分号后紧跟的两个字符不都是十六进制值。则不存在URL编码
    for (i=0; i<g_nCountPC; i++)
    {
        j = g_arrnPosPC[i];
        if ( !(IsHex(pszBuff+j+1) && IsHex(pszBuff+j+2)) )
        {
            // 仅仅要有一个百分号的字符不是十六进制值,都判定为不存在URL编码
            DbgMsgPrint("the char after % isn‘t a hex!");
            g_nIsEncodedbyURL = IDENTIFIY_RES_FALSE;
            return true;
        }
    }
    // 全部的百分号后面紧跟的都为2个十六进制数,才干基本肯定使用了URL编码
    g_nIsEncodedbyURL = IDENTIFIY_RES_CERTAIN;

    return true;
}

  • QP编码的特点是在等于号’=’紧跟两个十六进制数(字母必大写),因此我们须要在输入字节流中找到’=’号的位置,判定其后两个字符是否为十六进制值。而且若为’A’-‘F’的话,必须是大写字符。

    若全都不符合,则不可能为QP编码。若有符合条件的。还需继续判定全部的换行符”\r\n”之间的间隔长度是否全都小于76,若不符合,则也不可能是QP编码;这些条件都符合的。则有非常大可能是QP编码。-----存在型判定

QP编码判定函数实现例如以下:

// 判定是否存在QP编码
//參数 pszBuff,   待判定字符序列
//返回 一切正常,返回 true
bool IsEncodedbyQP(char *pszBuff)
{
    int i,j;

    // 等于号 数量上是否正常
    if (g_nCountEQ == ARRAY_MAX_SIZE)
        DbgMsgPrint("Please make the buffer size bigger for ‘=‘.");
    else if (g_nCountEQ == 0)
        return true;

    // 等于号 数量正常的话, 遍历待判定字符序列中全部的等于号【已由预处理的时候取得】
    for (i=0; i<g_nCountEQ; i++)
    {
        j = g_arrnPosEQ[i];
        // 对于QP编码,等于号后面的两个字符要么是十六进制值(字母的话需大写),要么是 \r\n
        if ( RegnizeChar(pszBuff+j+1)<=0 || RegnizeChar(pszBuff+j+2)<=0)
        {
            if( *(pszBuff+j+1)!=‘\r‘ || *(pszBuff+j+2)!=‘\n‘ )
            {
                // 仅仅要有一个等于号后面的字符不符合,就不是QP编码
                g_nIsEncodedbyQP = IDENTIFIY_RES_FALSE;
                return true;
            }
        }
    }
    // 全部的等于号后面紧跟的字符都符合,才干说可能使用了QP编码
    g_nIsEncodedbyQP = IDENTIFIY_RES_MAYBE;

    for (i=0; i<g_nConutCR-1; i++)
    {
        // 查看每一行的长度【对于QP编码,两个 \r\n 之间的字符序列长度不应超过限定值,通常是76】
        if(g_arrnPosCR[i+1] - g_arrnPosCR[i] > LINE_MAX_LENGTH+1)
            return true;
    }
    // 行长度都小于限定值,则能基本肯定使用了QP编码
    g_nIsEncodedbyQP = IDENTIFIY_RES_CERTAIN;

    return true;
}

  • Unicode编码的特点是”\u”后紧跟四个十六进制数(大写和小写皆可),因此我们须要在输入字节流中找到反斜线’\’的位置,判定其后紧跟的字符是否为’u’,若是再后面跟的四个字符是十六进制数,则能够确定使用了Unicode编码;反之所找不到这种模式串,则不可能使用了Unicode编码。-----存在型判定

Unicode编码判定函数实现例如以下

// 判定是否存在Unicode编码
//參数 pszBuff,   待判定字符序列
//返回 一切正常,返回 true
bool IsEncodedbyUnicode(char *pszBuff)
{
    int i,j;

    // 反斜杆 数量上是否正常
    if (g_nCountBS == ARRAY_MAX_SIZE)
        DbgMsgPrint("Please make the buffer size bigger for ‘\‘.");
    else if (g_nCountBS == 0)
        return true;

    // 反斜杆 数量正常的话, 遍历待判定字符序列中全部的反斜杆【已由预处理的时候取得】
    for (i=0; i<g_nCountBS; i++)
    {
        j = g_arrnPosBS[i];
        if (*(pszBuff+j+1)==‘u‘) // 反斜杆后面紧跟的字符是否为’u’
        {
            // ”\u”后紧跟的四个字符是否为十六进制数
            if ( IsHex(pszBuff+j+2) && IsHex(pszBuff+j+3) && IsHex(pszBuff+j+4) && IsHex(pszBuff+j+5) )
            {
                // 仅仅要有一个符合条件的,就能够觉得一定存在Unicode编码
                g_nIsEncodedbyUnicode = IDENTIFIY_RES_CERTAIN;
                return true;
            }
        }
    }
    // 全部的反斜杆后面的字符都不符合条件,才确认不存在Unicode编码
    g_nIsEncodedbyUnicode = IDENTIFIY_RES_FALSE;

    return true;
}
  • HTML特殊实体编码的特点是在取地址符’&’和分号’;’之间放实体名或实体编号。实体命名使用26个英文字母(大写和小写皆可),实体编号是以’#’開始的十进制数。所以我们判定时。须要找到全部’&’和’;’的位置。判定每一个’&’与离它近期的’;’之间的字符串,是否符合实体命名或编号的规范。若有符合这些要求的,则能够大概判定使用了HTML编码。反之,肯定没使用HTML特殊实体编码。

    -----存在型判定

HTML特殊实体编码判定函数实现例如以下

// 判定是否存在HTML特殊字符编码
//參数 pszBuff,   待判定字符序列
//返回 一切正常,返回 true
bool IsEncodedbyHtml(char *pszBuff)
{
    int i,j,nTemp;
    bool bFindSC;

    // 取址符与分号 数量上是否正常
    if (g_nCountAMP == ARRAY_MAX_SIZE)
        DbgMsgPrint("Please make the buffer size bigger for ‘&‘.");
    if (g_nCountSC == ARRAY_MAX_SIZE)
        DbgMsgPrint("Please make the buffer size bigger for ‘;‘.");

    if (g_nCountAMP==0 || g_nCountSC==0)
        return true;

    nTemp = 0;
    for (i=0; i<g_nCountAMP; i++)
    {
        bFindSC = false;
        for (j=nTemp; j<g_nCountSC; j++)
        {
            if ( g_arrnPosSC[j]>g_arrnPosAMP[i] )
            {
                bFindSC = true;
                break;
            }
        }
        if (!bFindSC)
            continue;

        nTemp = j;
        if (*(pszBuff+g_arrnPosAMP[i]+1) == ‘#‘)
        {
            for (j=g_arrnPosAMP[i]+2; j<g_arrnPosSC[nTemp]; j++)
            {
                if (RegnizeChar(pszBuff+j) != 2)
                {
                    g_nIsEncodedbyHtml = IDENTIFIY_RES_FALSE;
                    return true;
                }
            }
        }
        else
        {
            for (j=g_arrnPosAMP[i]+1; j<g_arrnPosSC[nTemp]; j++)
            {
                if ( *(pszBuff+j)>=‘A‘ && *(pszBuff+j)<=‘Z‘)
                    continue;
                else if ( *(pszBuff+j)>=‘a‘ && *(pszBuff+j)<=‘z‘)
                    continue;

                g_nIsEncodedbyHtml = IDENTIFIY_RES_FALSE;
                return true;
            }
        }

        g_nIsEncodedbyHtml = IDENTIFIY_RES_CERTAIN;
        break;
    }
    return true;
}

  • Base64编码的特点是编码后的结果仅仅可能出现64个特定字符、换行符、等于号。而且长度必为4的倍数。因此,我们判定的时候首先检查有没有超出范围的非法字符;假设没有,接着检查等于号是否仅仅出如今最后,而且数量不大于2;假设符合,继续检查输入总长度减去换行符长度后得到的值是否为4的倍数。这些条件仅仅要有一个不符合,都不可能是Base64编码,反之则有可能是Base64编码。

    -----是非型判定

  • MD5散列输出的长度通常是128bits,一般使用32个十六进制数表示。

    因此。我们判定的时候首先检查输入里面是否存在非16进制数的非法字符。再检查长度是否为32,都符合,则可能是MD5散列,反之。一定不是MD5散列。

    -----是非型判定

  • SHA1散列输出的长度通常是160bits。一般使用40个十六进制数表示。因此。我们判定的时候首先检查输入里面是否存在非16进制数的非法字符,再检查长度是否为40,都符合。则可能是SHA1散列,反之,一定不是SHA1散列。-----是非型判定

Base64编码判定【兼带判定是否为 MD5/SHA1 散列】的函数实现例如以下

// 判定是否为Base64编码
// 顺带判定是否为 MD5/SHA1 散列
//參数 pszBuff,   待判定字符序列
//返回 一切正常,返回 true
bool IsEncodedbyBase64(void)
{
    int nRealLength,i;

    // 先检查预处理的时候有没有遇到非法字符【对于Base64编码】
    if ( g_nIsEncodedbyBase64 == IDENTIFIY_RES_FALSE )
    {
        return true;
    }
    else if (g_nCountEQ > 2)
    {
        g_nIsEncodedbyBase64 = IDENTIFIY_RES_FALSE;
        return true;
    }

    // 当数据源为文件,且完整的数据都已被读进来来时。检查长度是否为4的倍数
    if ( (g_pszEncodedFilePath != NULL) && (g_nEncodedCotentLength >= BUFFER_MAX_SIZE) )
    {
        DbgMsgPrint("The buffer is too small for the whole file, can‘t regnize the Base64/MD5/SHA1!");
        return true;
    }
    nRealLength = g_nEncodedCotentLength - g_nConutCR - g_nCountLF; // 获取字符序列的实际长度(除去回车、换行)
    if ( nRealLength%4 != 0 )
    {
        // 基于Base64、MD5、SHA1的输出字符序列的特点,真实长度不为4的倍数的话,不可能是Base64/MD5/SHA1
        g_nIsEncodedbyBase64 = IDENTIFIY_RES_FALSE;
        g_nIsEncodedbyMD5   = IDENTIFIY_RES_FALSE;
        g_nIsEncodedbySHA1  = IDENTIFIY_RES_FALSE;

        return true;
    }

    // 经Base64编码的字符序列。其最后一个或最后两个字符可能是等号; 而MD5、SHA1的输出字符序列中不含等号
    if ( g_nCountEQ > 0)
    {
        for (i=0; i<g_nCountEQ; i++)
        {
            // 等号是否在最后一个或两个
            if (g_arrnPosEQ[i] < g_nEncodedCotentLength-2)
            {
                g_nIsEncodedbyBase64 = IDENTIFIY_RES_FALSE;
                return true;
            }
        }
        g_nIsEncodedbyBase64 = IDENTIFIY_RES_MAYBE;
    }
    else
    {
        g_nIsEncodedbyBase64 = IDENTIFIY_RES_MAYBE;

        // MD5散列输出的长度通常是128bits,一般使用32个十六进制数表示
        // SHA1散列输出的长度通常是160bits,一般使用40个十六进制数表示
        // 可通过长度对二者进行简单的区分
        if (nRealLength == 32)
        {
            g_nIsEncodedbyMD5   = IDENTIFIY_RES_MAYBE;
            g_nIsEncodedbySHA1  = IDENTIFIY_RES_FALSE;
            return true;
        }
        else if (nRealLength == 40)
        {
            g_nIsEncodedbySHA1  = IDENTIFIY_RES_MAYBE;
            g_nIsEncodedbyMD5   = IDENTIFIY_RES_FALSE;
            return true;
        }
    }

    return true;
}

        前面提到的七种变换算法的识别方法中。提到了两个名词。存在型判定是非型判定

对于存在型判定,我们判定的是输入中是否存在某种变换算法;而对于是非型判定,我们判定的是整个输入是否总体使用了某种变换算法。因为这样的差别。我们在这实现是非型判定的时候。就要求输入必须是完整的。(我在程序中用读入的长度是否小于输入缓存size来简单地判定)。

        在前文提到的七种变换算法的识别方法中,非常多都须要对一些特殊字符进行定位,比如:百分号’%’(URL编码),等于号’=’(QP编码、Base64编码),反斜线’\’(Unicode编码)。等等。

而这些特殊字符在原始输入字符序列中的位置和出现次数。都由一个预处理函数完毕【前文的几个判定函数实现中,也有提到】,事实上现例如以下:

// 对待判定字符序列的预处理
//參数 pszBuff,   待判定字符序列
//參数 nBuffSize, 待判定字符序列的长度
//返回 若一切正常。返回 true
bool PreProcess(char *pszBuff, int nBuffSize)
{
    int i;

    for (i=0; i<nBuffSize; i++)
    {
        if (IsHex(pszBuff+i))
            continue;
        else
        {
            // 出现非十六进制值,则必定不可能是 MD5/SHA1 散列编码
            g_nIsEncodedbyMD5  = IDENTIFIY_RES_FALSE;
            g_nIsEncodedbySHA1 = IDENTIFIY_RES_FALSE;
        }

        if ((*(pszBuff+i)>=‘G‘ && *(pszBuff+i)<=‘Z‘) ||
            (*(pszBuff+i)>=‘g‘ && *(pszBuff+i)<=‘z‘) ||
            *(pszBuff+i)==‘+‘ || *(pszBuff+i)==‘-‘)
        {
            continue;
        }
        else if (*(pszBuff+i)==‘\r‘)
        {
            if (g_nConutCR < ARRAY_MAX_SIZE)
                g_arrnPosCR[g_nConutCR++] = i;  // 记录回车符 \r 出现的位置与次数
            continue;
        }
        else if (*(pszBuff+i)==‘\n‘)
        {
            if (g_nCountLF < ARRAY_MAX_SIZE)
                g_arrnPosLF[g_nCountLF++] = i;  // 记录换行符 \n 出现的位置与次数
            continue;
        }
        else if (*(pszBuff+i)==‘=‘)
        {
            if (g_nCountEQ < ARRAY_MAX_SIZE)
                g_arrnPosEQ[g_nCountEQ++] = i;  // 记录等于号 = 出现的位置与次数
        }
        else
        {
            // 超出了 BASE64 编码结果集的范围
            g_nIsEncodedbyBase64 = IDENTIFIY_RES_FALSE;
        }

        if (*(pszBuff+i)==‘\\‘)
        {
            if (g_nCountBS < ARRAY_MAX_SIZE)
                g_arrnPosBS[g_nCountBS++] = i;  // 记录反斜杆 \\ 出现的位置与次数
        }
        else if (*(pszBuff+i)==‘%‘)
        {
            if (g_nCountPC < ARRAY_MAX_SIZE)
                g_arrnPosPC[g_nCountPC++] = i;  // 记录百分号 % 出现的位置与次数
        }
        else if (*(pszBuff+i)==‘&‘)
        {
            if (g_nCountAMP < ARRAY_MAX_SIZE)
                g_arrnPosAMP[g_nCountAMP++] = i;  // 记录取址符 & 出现的位置与次数
        }
        else if (*(pszBuff+i)==‘;‘)
        {
            if (g_nCountSC < ARRAY_MAX_SIZE)
                g_arrnPosSC[g_nCountSC++] = i;  // 记录分号 ; 出现的位置与次数
        }
    }

    return true;
}


代码实现:

 main.cpp 主程序文件内容       

#include "base.h"

char *g_pszExecPath = NULL;
int g_nWorkMode = 0;
char *g_pszEncodedFilePath = NULL;
char *g_pszEncodedCotent   = NULL;
int g_nEncodedCotentLength = 0;
int g_arrnPosCR[ARRAY_MAX_SIZE]; //回车符 \r 0D 13 位置记录
int g_arrnPosLF[ARRAY_MAX_SIZE]; //换行符 \n 0A 10 位置记录
int g_arrnPosBS[ARRAY_MAX_SIZE]; //反斜线 \\ 5C 92 位置记录
int g_arrnPosEQ[ARRAY_MAX_SIZE]; //等于号  = 3D 61 位置记录
int g_arrnPosPC[ARRAY_MAX_SIZE]; //百分号  % 25 37 位置记录
int g_arrnPosAMP[ARRAY_MAX_SIZE];//取地址符& 26 38 位置记录
int g_arrnPosSC[ARRAY_MAX_SIZE]; //分号    ; 3b 59 位置记录
int g_nConutCR = 0;
int g_nCountLF = 0;
int g_nCountBS = 0;
int g_nCountEQ = 0;
int g_nCountPC = 0;
int g_nCountAMP= 0;
int g_nCountSC = 0;
// 识别结果
int g_nIsEncodedbyURL     = IDENTIFIY_RES_UNKNOW;
int g_nIsEncodedbyQP      = IDENTIFIY_RES_UNKNOW;
int g_nIsEncodedbyUnicode = IDENTIFIY_RES_UNKNOW;
int g_nIsEncodedbyHtml    = IDENTIFIY_RES_UNKNOW;
int g_nIsEncodedbyBase64  = IDENTIFIY_RES_UNKNOW;
int g_nIsEncodedbyMD5     = IDENTIFIY_RES_UNKNOW;
int g_nIsEncodedbySHA1    = IDENTIFIY_RES_UNKNOW;
// 函数声明
bool GetParam(char* argv[]);
bool GetExecPath(void);
int RegnizeChar(char*);
bool IsHex(char*);
bool PreProcess(char*, int);
bool IsEncodedbyURL(char*);
bool IsEncodedbyQP(char*);
bool IsEncodedbyUnicode(char*);
bool IsEncodedbyHtml(char*);
bool IsEncodedbyBase64(void);
bool FreeGloabl(char*);


int main(int argc, char* argv[])
{
    int nFileHandle;
    char szReadTemp[BUFFER_MAX_SIZE];
    size_t nReadSize;
    const char *pszPrintInfo[4];
    pszPrintInfo[0] = "IDENTIFIY_RES_FALSE";
    pszPrintInfo[1] = "IDENTIFIY_RES_UNKNOW";
    pszPrintInfo[2] = "IDENTIFIY_RES_MAYBE";
    pszPrintInfo[3] = "IDENTIFIY_RES_CERTAIN";

    // 參数个数合法性判定
    if (argc != 3)
    {
        DbgErrPrint("Invalid count of parameter! \nUse this commnd like:\n             \tIdentify -s [encoded content]\n             or\n             \tIdentify -f [filename]");
        return -1;
    }

    // 获取參数值
    if (!GetParam(argv))
    {
        DbgErrPrint("Invalid value of parameter! \nUse this commnd like:\n             \tIdentify -s [encoded content]\n             or\n             \tIdentify -f [filename]");
        return -1;
    }

    // 若待判定的是一个文件,则需将文件内容读出
    if (g_nWorkMode == IDENTIFIY_SRC_FILE)
    {
        nFileHandle = open (g_pszEncodedFilePath, O_RDONLY);
        if (nFileHandle == -1)
        {
            DbgSysErrPrint("Open encoded file failed!");
            return -1;
        }

        nReadSize = read(nFileHandle, szReadTemp, BUFFER_MAX_SIZE);
        close(nFileHandle);
        switch(nReadSize)
        {
        case -1:
            DbgSysErrPrint("Read from encoded file failed!");
            return -1;
        case 0:
            DbgErrPrint("Empty encoded file!");
            return -1;
        default:
            g_pszEncodedCotent = szReadTemp;
            g_nEncodedCotentLength = nReadSize;
        }
    }

    // 预处理
    if (!PreProcess(g_pszEncodedCotent, g_nEncodedCotentLength))
    {
        DbgErrPrint("PreProcess failed!");
        return -1;
    }

    // 依次判定各种编码的可能性
    IsEncodedbyURL(g_pszEncodedCotent);
    IsEncodedbyUnicode(g_pszEncodedCotent);
    IsEncodedbyQP(g_pszEncodedCotent);
    IsEncodedbyHtml(g_pszEncodedCotent);
    IsEncodedbyBase64();

    // 打印结果
    DbgMsgPrint("URL/URI          encode identification result: %s", pszPrintInfo[g_nIsEncodedbyURL+1]);
    DbgMsgPrint("Quoted-Printable encode identification result: %s", pszPrintInfo[g_nIsEncodedbyQP+1]);
    DbgMsgPrint("Unicode          encode identification result: %s", pszPrintInfo[g_nIsEncodedbyUnicode+1]);
    DbgMsgPrint("Html special     encode identification result: %s", pszPrintInfo[g_nIsEncodedbyHtml+1]);
    DbgMsgPrint("Base64           encode identification result: %s", pszPrintInfo[g_nIsEncodedbyBase64+1]);
    DbgMsgPrint("MD5 hash         encode identification result: %s", pszPrintInfo[g_nIsEncodedbyMD5+1]);
    DbgMsgPrint("SHA1 hash        encode identification result: %s", pszPrintInfo[g_nIsEncodedbySHA1+1]);

    FreeGloabl(argv[2]);

    return 0;
}

// 获取程序的启动參数
//參数 argv, 程序启动參数列表
bool GetParam(char* argv[])
{
    if (strncmp(argv[1], "-s", 2)==0)  // 要判定的字符序列直接通过參数传进来
    {
        g_nWorkMode = IDENTIFIY_SRC_STRING;
        g_pszEncodedCotent = argv[2];
        g_nEncodedCotentLength = strlen(g_pszEncodedCotent);
        DbgMsgPrint("Identify string: %s", g_pszEncodedCotent);
        return true;
    }
    else if (strncmp(argv[1], "-f", 2)==0)  //要判定的是一个文件
    {
        g_nWorkMode = IDENTIFIY_SRC_FILE;
        if (argv[2][0] == ‘/‘)
        {
            g_pszEncodedFilePath = argv[2];
        }
        else
        {
            if (!GetExecPath())
            {
                DbgErrPrint("Get the path of Identify failed!");
                return false;
            }
            g_pszEncodedFilePath = new char[strlen(g_pszExecPath)+strlen(argv[2])+1];
            ASSERT(g_pszEncodedFilePath!=NULL);
            strcpy(g_pszEncodedFilePath, g_pszExecPath);
            strcat(g_pszEncodedFilePath, argv[2]);
        }
        DbgMsgPrint("Identify file: %s", g_pszEncodedFilePath);
        return true;
    }

    return false;
}

// 获取可运行文件所在的文件夹路径
//返回 成功返回true
bool GetExecPath(void)
{
    char szExecPath[512];
	int nCount;
	int i;

	//先获取可运行文件的路径
	nCount = readlink("/proc/self/exe", szExecPath, sizeof(szExecPath));
	if (nCount == -1)
	{
		DbgErrPrint("Readlink failed!");
		return false;
	}

	//提取可运行文件所在的文件夹路径
	szExecPath[nCount] = ‘\0‘;  // 字符数组转换成C字符串
	for (i=nCount-1; i>0; i--)
	{
		if (szExecPath[i-1] == ‘/‘)
			break;
	}
	if (i == 0)  //不存在文件夹分隔符
	{
		DbgErrPrint("Get exec path failed!");
		return false;
	}
	szExecPath[i] =‘\0‘;

	g_pszExecPath = new char[i+1];
	ASSERT(g_pszExecPath != NULL);
	strcpy(g_pszExecPath, szExecPath);

    return true;
}

// 识别输入字符的类型
//參数 pszValue, 指向待识别的字符
//返回 若为数字,返回 2;  若为大写英文字符,返回 1; 若为小写英文字符,返回 0; 若都不是。返回 -1.
int RegnizeChar(char *pszValue)
{
    if (*pszValue>=‘0‘ && *pszValue<=‘9‘)
        return 2;
    else if (*pszValue>=‘A‘ && *pszValue<=‘F‘)
        return 1;
    else if (*pszValue>=‘a‘ && *pszValue<=‘f‘)
        return 0;
    else
        return -1;
}

// 判定输入字符是否可能是十六进制值
//參数 pszValue, 指向待识别的字符
//返回 若识别为非16进制值。返回 false; 反之,返回 true.
bool IsHex(char *pszValue)
{
    if (RegnizeChar(pszValue)<0)
        return false;

    return true;
}

/*此处略去预处理函数与几个判定函数的定义,參看前文 */

// 释放全局变量
//參数 pszParam【输入】,最后一个启动參数
//返回 成功返回true
bool FreeGloabl(char *pszParam)
{
    if (g_pszExecPath != NULL)
    {
        delete [] g_pszExecPath;
        g_pszExecPath = NULL;
    }

    // 仅当启动參数为相对路径时,才须要释放
    if (g_pszEncodedFilePath != NULL && g_pszEncodedFilePath != pszParam)
    {
        delete [] g_pszEncodedFilePath;
        g_pszEncodedFilePath = NULL;
    }

    return true;
}

base.h 头文件内容:

#ifndef ENCODEIDENTIFIY_BASE_H
#define ENCODEIDENTIFIY_BASE_H

#include <stdio.h>          //ANSI标准 输入输出
#include <stdlib.h>         //ANSI标准 经常使用函数库
#include <time.h>           //ANSI标准 日期与时间处理
#include <signal.h>         //ANSI标准 信号处理
#include <errno.h>          //ANSI标准 错误码定义
#include <assert.h>         //ANSI标准 验证程序断言
#include <unistd.h>         //POSIX 符号常量( 系统经常使用API的封装 )
#include <strings.h>        //POSIX 字符串处理( 基本相似标准的string.h )
#include <fcntl.h>          //POSIX 文件操作
#include <sys/stat.h>       //POSIX 文件属性
#include <sys/types.h>      //POSIX 基本系统数据类型

#include <string>

using namespace std;

// 定义是否使用调试模式
#define DEBUG
// 定义调试宏
#ifdef DEBUG
	#define ASSERT(_x_)         assert(_x_)
	#define DbgSysErrPrint(_x_) perror(_x_)
	#define DbgMsgPrint(format,...) printf(format"\n", ##__VA_ARGS__)
	#define DbgErrPrint(format,...) printf("File: "__FILE__", Line: %05d, Func: %s ---> "format"\n", __LINE__, __FUNCTION__, ##__VA_ARGS__)
#else
	#define ASSERT(_x_)
	#define DbgSysErrPrint(_x_)
	#define DbgMsgPrint(format,...)
	#define DbgErrPrint(format,...)
#endif

#define ARRAY_MAX_SIZE  512
#define BUFFER_MAX_SIZE 2048
#define LINE_MAX_LENGTH 76

// 定义识别来源
#define IDENTIFIY_SRC_STRING  1   // 识别字符串
#define IDENTIFIY_SRC_FILE    2   // 识别文件
// 定义识别结果
#define IDENTIFIY_RES_CERTAIN 2   // 确认是某种编码
#define IDENTIFIY_RES_MAYBE   1   // 可能是某种编码
#define IDENTIFIY_RES_UNKNOW  0   // 无法确认
#define IDENTIFIY_RES_FALSE  -1   // 确认不是某种编码

// 可供外部文件调用的全局变量声明
extern char *g_pszExecPath;
extern int g_nWorkMode;
extern char *g_pszEncodedFilePath;
extern char *g_pszEncodedCotent;
extern int g_nEncodedCotentLength;

#endif // ENCODEIDENTIFIY_BASE_H





















以上是关于Linux工具开发[02]---编程实现对输入字符序列变换(编码/加密/散列)方式的智能判定的主要内容,如果未能解决你的问题,请参考以下文章

Shell编程——Expect免交互

Linux vi/vim

第1章 Linux系统编程入门——Linux开发环境搭建

awk命令介绍

Linux之三剑客

linux编程开发命令