C/C++知识点之linux 下字符混淆器
小标 2019-05-08 来源 : 阅读 1088 评论 0

摘要:本文主要向大家介绍了C/C++知识点之linux 下字符混淆器,通过具体的内容向大家展示,希望对大家学习C/C++知识点有所帮助。

本文主要向大家介绍了C/C++知识点之linux 下字符混淆器,通过具体的内容向大家展示,希望对大家学习C/C++知识点有所帮助。

C/C++知识点之linux 下字符混淆器

//gcc elfscure.c -o elfscure#include <stdio.h>#include <string.h>#include <stdlib.h>#include <unistd.h>#include <fcntl.h>#include <errno.h>#include <elf.h>#include <sys/stat.h>#include <sys/mman.h>#include <sys/time.h>#include <time.h>#define SHT_VERSYM  0x6fffffff#define SHT_VERNEED 0x6ffffffe//SHF_WRITE#define W 1//SHF_ALLOC#define A 2//SHF_EXECINSTR#define X 4//功能struct options{    //字符串表随机化    char smix;    char verbose;    //保持与字符串名称一致的区段类型    char sh_type;    //保持区段标志与字符串名称一致    char sh_flags;

} opts;struct stat st;//节类型struct section_type {    char name[64];    uint32_t type;    int flags;
};struct section_type section_type[] = {{"".interp"",           SHT_PROGBITS,     A },
{"".hash"",         SHT_HASH,         A },
{"".note.ABI-tag"",  SHT_NOTE,        A },
{"".gnu.hash"",     SHT_GNU_HASH,     A },
{"".dynsym"",       SHT_DYNSYM,       A },
{"".dynstr"",       SHT_STRTAB,       A },
{"".gnu.version"",   SHT_VERSYM,      A },
{"".gnu.version_r"", SHT_VERNEED,     A },
{"".rel.dyn"",          SHT_REL,          A },
{"".rel.plt"",          SHT_REL,          A },
{"".init"",         SHT_PROGBITS,     A|X},
{"".plt"",              SHT_PROGBITS,     A|X},
{"".text"",         SHT_PROGBITS,     A|X},
{"".fini"",         SHT_PROGBITS,     A|X},
{"".rodata"",       SHT_PROGBITS,     A },
{"".eh_frame_hdr"",  SHT_PROGBITS,        A },
{"".eh_frame"",     SHT_PROGBITS,     A },
{"".ctors"",        SHT_PROGBITS,     W|A},
{"".dtors"",        SHT_PROGBITS,     W|A},
{"".jcr"",              SHT_PROGBITS,     W|A},
{"".dynamic"",          SHT_DYNAMIC,      W|A},
{"".got"",              SHT_PROGBITS,     W|A},
{"".got.plt"",          SHT_PROGBITS,     W|A},
{"".data"",         SHT_PROGBITS,     W|A},
{"".bss"",              SHT_NOBITS,       W|A},
{"".shstrtab"",      SHT_STRTAB,      0 },
{"".symtab"",       SHT_SYMTAB,       0 },
{"".strtab"",       SHT_STRTAB,       0 },
{"""",              SHT_NULL            }
};//用于获取节名的新偏移量int STBL_OFFSET(char *p, char *string, int count){    char *offset = p;    while (count-- > 0)
    {        while (*offset++ != '.')
            ;        if (strcmp(string, offset-1) == 0)            return ((offset - 1) - p);        //有的节名有俩种        if (!strncmp(offset-1, "".rel."", 5) || !strncmp(offset-1, "".gnu."", 5) 
        ||  !strncmp(offset-1, "".not."", 5) || !strncmp(offset-1, "".got."", 5))            while (*offset++ != '.');

    }    return 0;
}int strused(char *s, char **used_strings, int count){    int i;    for (i = 0; i < count; i++)        if (!strcmp(s, used_strings[i]))            return 1;    return 0;
}int main(int argc, char **argv){   //文件头
    Elf32_Ehdr *ehdr;    //节表
    Elf32_Shdr *shdr, *shp;    //程序头
    Elf32_Phdr *phdr;    //字符串表    char *StringTable, *NewStringTable;    char **STBL, **STBL_USED_STRINGS;    char *p, exec[255];    char tmp[64];    //映射基址    uint8_t *mem;    int fd;    int i, j, k, count;    int strcnt, slen;    char c, failed = 0;    struct timeval tv;    struct timezone tz;

    opts.smix = 0;
    opts.verbose = 0;
    opts.sh_type = 0;
    opts.sh_flags = 0;    if (argc < 3)
    {        printf(""\n- Elf 二进制混淆器\n""        ""用法: %s <文件> [选项]\n""        ""[-s]    字符串表随机化 \n""        ""[-t]   保持与字符串名称一致的区段类型\n""        ""[-f]    保持区段标志与字符串名称一致\n""        ""如: \n""        ""%s evilprog -stf\n"",
        argv[0], argv[0]);  
        exit(0);
    }    strcpy(exec, argv[1]);    //获取选项    while ((c = getopt(argc, argv, ""fstv"")) != -1)
    {        switch(c)
        {            case 's':
                opts.smix++;                break;            case 't':
                opts.sh_type++;                break;            case 'f':
                opts.sh_flags++;                break;            case 'v':
                opts.verbose++;                break;
        }
    }    //打开文件    if ((fd = open(exec, O_RDWR)) == -1)
    {
        perror(""open"");        exit(-1);
    }    //读文件描述符    if (fstat(fd, &st) < 0)
    {
        perror(""fstat"");        exit(-1);
    }    //映射
    mem = mmap(0, st.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);    if (mem == MAP_FAILED)
    {
        perror(""mmap"");        exit(-1);
    }    //文件头
    ehdr = (Elf32_Ehdr *)mem;    //程序头
    phdr = (Elf32_Phdr *)(mem + ehdr->e_phoff);    //节表头
    shdr = (Elf32_Shdr *)(mem + ehdr->e_shoff);    //设置字符串表指针
    StringTable = &mem[shdr[ehdr->e_shstrndx].sh_offset];    printf(""[+] ELF Section 混淆 ->\n"");    printf(""[+] 开始字符串表随机化 \n"");    if (opts.sh_type)        printf(""[+] sh_type一致性启用\n"");    if (opts.sh_flags)        printf(""[+] sh_flag一致性启用\n"");    if (opts.sh_type || opts.sh_flags)
        ehdr->e_shnum = 0;    //分配e_shnum个    if ((STBL = calloc(ehdr->e_shnum, sizeof(char *))) == NULL)
    {
        perror(""calloc"");        exit(-1);
    }    //分配e_shnum个    if ((STBL_USED_STRINGS = calloc(ehdr->e_shnum, sizeof(char *))) == NULL)
    {
        perror(""calloc"");        exit(-1);
    }    //遍历所有节    for (i = 0, shp = shdr; i < ehdr->e_shnum; shp++, i++)        //拷贝所有字符名称
        STBL[i] = strdup(&StringTable[shp->sh_name]); 
    strcnt = i - 1;    //先计算出长度    for (slen = 0, i = 0; i < strcnt; i++, slen += strlen(STBL[i]) + 1);    //再申请空间    if ((NewStringTable = (char *)malloc(slen)) == NULL)
    {
        perror(""malloc"");        exit(-1);
    }    //赋值    for (p = NewStringTable, i = 0; i < strcnt; i++)
    {        strcpy(p, STBL[i]); 
        p += strlen(p) + 1;
        *p = 0;
    }    if (opts.verbose)
    {        for (i = 0; i < slen; i++)            printf(""%c"", NewStringTable[i]);        printf(""\n"");
    }    for (i = 0; i < strcnt; i++)
        STBL_USED_STRINGS[i] = malloc(64);
    j = 0;    for (i = 0, shp = shdr; i < ehdr->e_shnum; i++, shp++)
    {        memset(tmp, 0, sizeof(tmp));
        gettimeofday(&tv, NULL);
        srand(tv.tv_usec);        //将随机段名称复制到TMP中        strcpy(tmp, STBL[rand() % strcnt]); 

        //字符串是否被使用        if (strused(tmp, STBL_USED_STRINGS, strcnt))
        {
            --i;
            --shp;            continue;
        }        //确认没有分配自己的副本        //.symtab .symtab        if (!strcmp(&StringTable[shp->sh_name], tmp))
        {
            --i; --shp;            continue;
        } 
        if (shp->sh_type == SHT_NULL)            continue;        //动态节就保持在适当的位置        if (!strcmp(&StringTable[shp->sh_name], "".dynamic"") || !strcmp(tmp, "".dynamic""))
        {            if ((shp->sh_name = STBL_OFFSET(NewStringTable, "".dynamic"", strcnt)) == 0)
            {                  printf(""STBL_OFFSET failed, could not find section name: %s, moving on\n"", tmp);                              goto done;
            }            continue;
        }        //创建新的偏移量        if ((shp->sh_name = STBL_OFFSET(NewStringTable, tmp, strcnt)) == 0)            printf(""STBL_OFFSET 失败, 找不到节名: %s\n"", tmp);        //代码段修改为0x8048000        if (!strcmp(tmp, "".text""))
            shp->sh_addr = 0x8048000;       //更改节类型以匹配其名称symtab、rel和dynsym类型需要特定的条目大小        if (opts.sh_type)            for (count = 0; count < strcnt; count++)                if (!strcmp(tmp, section_type[count].name))
                {   
                    shp->sh_type = section_type[count].type;                    if (shp->sh_type == SHT_SYMTAB)
                        shp->sh_entsize = 0x10;                    else                    if (shp->sh_type == SHT_DYNSYM)
                        shp->sh_entsize = 0x10;                    else                    if (shp->sh_type == SHT_REL)
                        shp->sh_entsize = 0x08;
                }        if (opts.sh_flags)            for (count = 0; count < strcnt; count++)                if (!strcmp(tmp, section_type[count].name))
                    shp->sh_flags = section_type[count].flags;        strcpy(STBL_USED_STRINGS[j++], tmp);
    }    //拷贝字符串表    memcpy(&mem[shdr[ehdr->e_shstrndx].sh_offset], NewStringTable, shdr[ehdr->e_shstrndx].sh_size);    //实现磁盘文件内容与共享内存区中的内容一致    if (msync(mem, st.st_size, MS_SYNC) == -1)
    {
        perror(""msync"");
        failed++;
    }

    done:    //解除映射
    munmap(mem, st.st_size);    for (i = 0; i < strcnt; i++)
    {   free(STBL[i]);        free(STBL_USED_STRINGS[i]);
    } 
    if (!failed)        printf(""段混淆成功!!!\n"");    else        printf(""段没有完全混淆!!!\n"");    exit(0);
}

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标编程语言C/C+频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程