本文主要向大家介绍了C/C++知识点之linux 下字符混淆器,通过具体的内容向大家展示,希望对大家学习C/C++知识点有所帮助。
//gcc elfscure.c -o elfscure#include #include #include #include #include #include #include #include #include #include #include #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
}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
{ 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)
{
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 e_shnum; shp++, i++) //拷贝所有字符名称
STBL[i] = strdup(&StringTable[shp->sh_name]);
strcnt = i - 1; //先计算出长度 for (slen = 0, i = 0; i
{
perror(""malloc""); exit(-1);
} //赋值 for (p = NewStringTable, i = 0; i
{ strcpy(p, STBL[i]);
p += strlen(p) + 1;
*p = 0;
} if (opts.verbose)
{ for (i = 0; i
} for (i = 0; i
STBL_USED_STRINGS[i] = malloc(64);
j = 0; for (i = 0, shp = shdr; i 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
{
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
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
{ free(STBL[i]); free(STBL_USED_STRINGS[i]);
}
if (!failed) printf(""段混淆成功!!!\n""); else printf(""段没有完全混淆!!!\n""); exit(0);
}
本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标编程语言C/C+频道!