摘要:本文主要向大家介绍了C/C++知识点之linux 下字符混淆器,通过具体的内容向大家展示,希望对大家学习C/C++知识点有所帮助。
本文主要向大家介绍了C/C++知识点之linux 下字符混淆器,通过具体的内容向大家展示,希望对大家学习C/C++知识点有所帮助。
//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+频道!
您输入的评论内容中包含违禁敏感词
我知道了
请输入正确的手机号码
请输入正确的验证码
您今天的短信下发次数太多了,明天再试试吧!
我们会在第一时间安排职业规划师联系您!
您也可以联系我们的职业规划师咨询:
版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
沪公网安备 31011502005948号