1. 程式人生 > >linux 下字符混淆器

linux 下字符混淆器

exe break main uint8_t instr 文件內容 dup 副本 fine

//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); }

linux 下字符混淆器