关于C++中正则表达式的使用

1. 前言

在近期的科研过程中需要利用objdump对二进制软件进行一个静态分析,以提取该二进制可执行程序中调用的C标准库函数名,并得到函数名的索引在后续的动态分析中使用。coding过程中用到了正则表达式

2. 正则表达式

正则表达式是在字符串处理中的常用工具,主要用于字符串的匹配。

1)例子

const string FUNC_LINE("<([a-z]+)@");  //设置匹配字符串
regex reg(FUNC_LINE);  //设置匹配正则表达式
smatch f; //存放匹配到的字符串
regex_search(line, f, reg); //搜索匹配(匹配子字符串)
string s = f[1].str(); //从搜索出的子字符串中找出匹配[a-z]+的子串

代码中"<([a-z]+)@",匹配以<开头的字符串,[a-z]+匹配多个字母字符,以@符号结尾。f[]数组表示匹配得出的子字符串:f[0]为整个"<([a-z]+)@"匹配的字符串;f[1]为"([a-z]+)"大子串中匹配第一个()中格式的子串。

例如:f[0]匹配得到"<printf@",则f[1]匹配得到"printf"。

2)regex_match函数

match是全文匹配,即要求整个字符串符合匹配规则。匹配成功返回true。

cout << regex_match("<<printf@", regex("<([a-z]+)@")) << endl; //输出0
cout << regex_match("<printf@", regex("<([a-z]+)@")) << endl;   //输出1

3)regex_search函数

search是搜索匹配,即搜索字符串中存在符合规则的子字符串。匹配成功返回true。

cout << regex_match("<<printf@", regex("<([a-z]+)@")) << endl;  //regex_match输出0
cout << regex_search("<<printf@", regex("<([a-z]+)@")) << endl;  //regex_search输出1

3. 实例

/*
 * author: kanxiao
 * date: 2020/06/16
 * 利用objdump静态分析可执行文件中调用的C标准库函数
 * 在libc_desc中的索引存入set
 *
*/

#include <iostream>
#include <fstream>
#include <string>
#include <regex>
#include <unordered_map>
#include <set>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>

using namespace std;


/* 建立哈希表,存储函数名与索引号的映射关系 */
const unordered_map<string, unsigned> libc_map = {

{"isalnum", 0}, {"isalpha", 1}, {"iscntrl", 2}, {"isdigit", 3}, {"isgraph", 4}, {"islower", 5}, {"isprint", 6}, {"ispunct", 7}, {"isspace", 8},
{"isupper", 9}, {"isxdigit", 10}, {"isctype", 11}, {"tolower", 12}, {"toupper", 13}, {"memcpy", 14}, {"memset", 15}, {"memchr", 16}, {"memcmp", 17},
{"strcat", 18}, {"strncat", 19}, {"strchr", 20}, {"strcmp", 21}, {"strncmp", 22}, {"strcoll", 23}, {"strcpy", 24}, {"strncpy", 25}, {"strcspn", 26},
{"strlen", 27}, {"strpbrk", 28}, {"strspn", 29}, {"strstr", 30}, {"strtok", 31}, {"strxfrm", 32}, {"atoi", 33}, {"calloc", 34}, {"realloc", 35},
{"malloc", 36}, {"abort", 37}, {"getenv", 38}, {"qsort", 39}, {"bsearch", 40}, {"abs", 41}, {"labs", 42}, {"rand", 43}, {"srand", 44}, {"free",45},
{"asctime", 46}, {"clock", 47}, {"time", 48}, {"ctime", 49}, {"gmtime", 50}, {"localtime", 51}, {"mktime", 52}, {"strftime", 53}, {"fclose", 54},
{"fopen", 55}, {"printf", 56}, {"fread", 57}, {"fwrite", 58}, {"puts", 59}, {"gets", 60}, {"fputs", 61}, {"fgets", 62}

};

const string FUNC_LINE("<([a-z]+)@");

//set for libc function index in libc_desc
set<unsigned> libc_idx;

int main(int argc, char *argv[])
{
    int rc = fork();
    if(rc < 0)
    {
        cerr << "fork failed!" << endl;
        exit(1);
    }
    //子进程
    else if(rc == 0)
    {
        /*重定向stdout到objdump.txt*/
        close(1);
        int fd = open("objdump.txt", O_WRONLY | O_TRUNC);
        if(fd < 0)
        {
            cerr << "open failed!" << endl;
            exit(1);
        }
        char *myargs[4];
        myargs[0] = "objdump";
        myargs[1] = "-d";
        myargs[2] = argv[1];
        myargs[3] = NULL;
        if(execvp(myargs[0], myargs) < 0)
        {
            cerr << "execvp failed" << endl;
            exit(1);
        }
        close(fd);
    }
    //进程本身
    else
    {
        wait(NULL); //保证子进程先运行结束

        ifstream f("./objdump.txt");
        if(!f)
        {
            cerr << "could not open objdump file" << endl;
            exit(1);
        }
        
        //正则表达式匹配
        string line;
        regex r(FUNC_LINE);
        while(getline(f, line))
        {
            smatch f;
            if(regex_search(line, f, r))
            {
                if(f.size() == 2)
                {
                    string s = f[1].str();
                    auto it = libc_map.find(s);
                    if(it != libc_map.end())
                        libc_idx.insert(it->second);
                }
            }
        }
        /*
        for(const auto & x : libc_idx)
            cout << x << '\t' << " ";
        */
        for(auto it = libc_idx.cbegin(); it != libc_idx.cend(); ++it)
        {
            if(it == libc_idx.cbegin())
                cout << *it;
            else
                cout << ", " << *it;
        }
    }
    cout << endl;

    return 0;
}

上述实例完成了前言部分的描述。运行结果:


objdump_analysis.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345