Objective-C代码混淆扩展:安全攻防之代码混淆工具详细指南

5 阅读3分钟

Objective-C代码混淆扩展----安全攻防之代码混淆的一个小工具iOS安全攻防

规则:

创建函数名列表func.list,写入待混淆的函数名,如:

-(void)sample;

-(void)seg1:(NSString *)string seg2:(NSUInteger)num;

就这样写:

sample

seg1

seg2

对于更全面的iOS应用保护,可以考虑使用专业的混淆工具如IpaGuard,它能够无需源码直接对IPA文件进行代码和资源混淆,提供更强的安全性。所以我用c语言写了以下的代码,专门用来生成func.list文件。

代码的功能是遍历你的工程,把里面的.h和.m文件找出来。并且把里面的类名,方法名,参数名等按上面的规则列出来。

注:因为一般.m和.h是配对的,比如test.m就有test.h,不过有时也只有config.h,而没有对应的.m文件。所以里面有一个小逻辑是如果有m文件,就不处理h文件,怕重复类名方法名等。

#include <stdio.h>  
#include <sys/types.h>  
#include <dirent.h>  
#include <string.h>  
#include <sys/stat.h>  
#include <unistd.h>  
   
  
//编译方法,  
//gcc file.c -o file  
//运行方法  
//./file  
//然后就会输出你工程里的类名方法名,就可以把这里组装成一个需要混淆的配置文件了。  
//缺限  
//1.输出名字没有做重复处理。  
//2.判断方法时只是处理了两种情况,如果空格多于2个没有处理。  
  
  
#if 0//放开调试  
#define Printf_info(x,y) printf(x,y);  
#else  
#define Printf_info(x,y)  
#endif  
   
  
int Mydir(const char *filepath);  
int checkFile(const char *filepath);  
  
int findNum = 0;  
  
int main(int argc, char *argv[])  
{  
    //此代码的功能是遍历ios的项目的所有。h和。m的文件,把里面的类名,方法名,参数名等都提取出来,  
    //方便用CSDN博主“念茜”的方法来混淆自己的代码用。  
        Mydir("/myProject");//填写自己的工程的根目录路径。  
  
        return 0;  
}  
void Print_fileName(const char * filename)  
{  
    int a = strlen(filename);  
    for(int i=0;i<a - 2; i++){  
        printf("%c",filename[i]);  
    }  
    printf("\n");  
}  
int Mydir(const char *filepath)  
{  
    char *fullpath,*filetype,*tmp;  
    struct stat statbuf;  
    DIR *dr;  
    struct dirent *drt;  
      
    if((dr=opendir(filepath))==NULL)  
        return 2;  
      
    while((drt=readdir(dr))!=NULL)  
    {  
          
        if(strcmp(drt->d_name,".")==0||strcmp(drt->d_name,"..")==0||strcmp(drt->d_name,".DS_Store")==0)  
            continue;  
          
        fullpath=strdup(filepath);  
        fullpath=strcat(fullpath,"/");  
        fullpath=strcat(fullpath,drt->d_name);  
          
        Printf_info("%s\n",fullpath);  
          
        if(stat(fullpath,&statbuf)<0)  
            continue;  
          
        if (S_ISREG(statbuf.st_mode))  
        {  
            filetype="reguler";  
            int a = strlen(drt->d_name);  
            char *pp = drt->d_name;  
            //printf("----  %c %c" , pp[a - 2], pp[a - 1]);  
              
            if(pp[a - 2] == '.' && pp[a - 1] == 'm')  
            {  
                Print_fileName(drt->d_name);  
                checkFile(fullpath);  
            }  
#if 0  
            else if(pp[a - 2] == '.' && pp[a - 1] == 'h')  
            {  
                char *mPath = strdup(fullpath);  
                //printf("\nmpath: %s\n",mPath);  
                char *ppp = mPath;//drt->d_name;  
                int a = strlen(ppp);  
                ppp[a - 1] = 'm';//检查m文件是否存在。  
                //printf("\nmpath: %s\n",mPath);  
                if((access(mPath,F_OK))==0){  
                    continue;  
                }  
                Print_fileName(drt->d_name);  
                checkFile(fullpath);  
            }  
#endif  
        }  
        else if(S_ISDIR(statbuf.st_mode))  
        {  
            filetype="directory";  
            //fullpath=strcat(fullpath,"/");  
            //printf("%s,%s\n",fullpath,filetype);  
            tmp=strdup(fullpath);  
            Mydir(tmp);  
        }  
        else  
        {  
            filetype="invalid";  
            printf("%s,%s\n",fullpath,filetype);  
        }  
        //printf("%s,%s\n",fullpath,filetype);  
        bzero(fullpath,strlen(fullpath));  
    }  
    return 0;  
}  
int print_Method(char *text)  
{  
    char *p = text;  
    char c;  
    int start = 0;  
    while((c = *p++) !='\n'){//Method  
        if(c == ':' || c == '{' || c == ';'){  
            start = 0;  
            break;  
        }  
        if(start == 1){  
            printf("%c", c);  
        }  
        if(c == ')')  
            start = 1;  
    }  
    printf("\n");  
#if 0  
    start = 0;  
    while((c = *p++) !='\n'){//arge  
        if(c == ':'){  
            start = 0;  
            printf("\n");  
        }  
        if(start == 2 && c != '{'){  
            printf("%c", c);  
        }  
        if(c == ' ' && start == 1)  
            start = 2;  
        if(c == ')')  
            start = 1;  
    }  
    //printf("\n");  
#endif  
    return 0;  
}  
int findMethod(char *text)  
{  
    char *p = text;  
    char c;  
    while((c = *p++) !='\n'){  
        if(c == '-' && ((*p == ' ' && *(p + 1) == '(') || *p == '(' )){  
            if( text[0] == '-' )  
            {  
                //printf("%d %s\n", findNum++, text);  
                print_Method(text);  
            }  
            //else  
            //  printf("%d %s\n", findNum++, text);  
        }  
        if(c == '+' && ((*p == ' ' && *(p + 1) == '(') || *p == '(' )){  
            if( text[0] == '+' )  
            {  
                //printf("%d %s\n", findNum++, text);  
                print_Method(text);  
            }  
            //else  
            //  printf("%d %s\n", findNum++, text);  
        }  
    }  
    return 0;  
}  
int checkFile(const char *filepath)  
{  
    //printf("====%s\n", filepath);  
      
    FILE *fp1;//定义文件流指针,用于打开读取的文件  
    char text[40961];//定义一个字符串数组,用于存储读取的字符  
    fp1 = fopen(filepath,"r");//只读方式打开文件a.txt  
    while(fgets(text,40960,fp1)!=NULL)//逐行读取fp1所指向文件中的内容到text中  
    {  
        //puts(text);//输出到屏幕  
        findMethod(text);  
    }  
    fclose(fp1);//关闭文件a.txt,有打开就要有关闭  
      
    return 0;  
}