1. Detect Android-server file
void check(){
const char* Path="/data/local/tmp";
dir =opendir(Path);
int pid =getpid();
if(dir!=NULL){
dirent *currentDir;
while((currentDir=readdir(dir)!=NULL)){
//使用readdir函数读取当前目录下的每一个文件
if(strncmp(currentDir->d_name,"android_server",14)==0)//currentDir->de_name结构体能够获取当前的文件名
{
kill(pid,SIGKILL);
}
}
closedir(dir);//关闭文件
}else{
}
}
Analysis :
This is the simplest kind of anti-debugging detection. The principle is very simple. Use currentDir
structure detection to obtain
/data/local/tmpIs there an android_server file in the directory
Countermeasures:
There are many countermeasures. The most convenient way is to enter the /data/local/tmp directory and change the file name.
2. Detection process name
This method has been analyzed before, here is a more detailed analysis
void check()
{
const int bufsize=1024;
char filename[bufsize];
char line[bufsize];
char name[bufsize];
char nameline[bufsize];
//获取Tracepid的值
int pid=getpid();
sprint(filename,"/proc/%d/status",pid);
FILE *fd=fopen(filename,"r");
if(fd!=NULL)
{
while(fgets(line,bufsize,fd))
{
//遍历读取到“TracePid”
if(strstr(line,"TracePid")!=NULL)
{
//判断TracePid的第10个数是否为0
int statue=atoi(&line[10]);
if(statue!=0)
{
//不等于0时,将当前的statue写入到name中
sprint(name,"/proc/%d/cmdline",statue);
//读取文件fdname
FILE *fdname=fopen(name,"r");
if(fdname!=NULL)
{
//遍历找到“android_server”
while(fgets(nameline,bufsize,fdname))
{
if(strstr(nameline,"android_server"!=NULL))
{
int ret =kill(pid,SIGKILL);
//kill进程
}
}
}
fclose(fdname);
}
}
}
}
fclose(fd);
}
strstr: Definition : char *strstr(const char *haystack, const char *needle) Function : haystack -C string to be retrieved. needle -The small string to be searched in the haystack string. This function returns the position where the needle string first appears in haystack, or null if it is not found .
atoi: definition : int atoi(const char *str), function : str-the string to be converted to an integer. This function returns the converted long integer, or zero if no effective conversion has been performed.
Analysis : first check whether the value of Tracepid is 0, if it is 0, check whether there is android_server in the traversal check, if there is a direct kill process
Countermeasures: Let’s simply talk about it. In general, we will try to break under ida and change its return value to 0 when running to the specified function. Of course, other methods such as nop off the jump instruction can also be used. , Let it not be detected, there is a more complicated way to fundamentally solve this anti-debugging problem, that is to refresh the machine to modify the source code, here is a post from a big guy https://se8s0n.github.io/2019/04/ 19/%E5%B0%9D%E8%AF%95%E7%BB%95%E8%BF%87TracePID%E5%8F%8D%E8%B0%83%E8%AF%95%E4%BA%8C %E2%80%94%E2%80%94%E4%BB%8E%E6%BA%90%E7%A0%81%E5%85%A5%E6%89%8B/
Three, detect commonly used ports
void check()
{
FILE* pfile=NULL;
char buf[0x10000]={
0};
//使用代码执行cmd命令
char* strCatTcpPort="cat /proc/net/tcp |grep :5D8A";
pfile = popen(strCatTcpPort,"r");
int pid=getpid();//获取进程的pid
if(NULL==pfile)
{
//命令运行失败
return;
}
//读取pfile文件内容,如果android_server没有启动的话,常文件内不会有内容
while(fgets(buf,sizeof(buf),pfile))
{
//检测到23946端口被占用,直接kill进程
int ret=kill(pid,SIGKILL);
}
pclose(pfile);
}
Analysis:
The cat /proc/net/tcp |grep :5D8A
command is used here to read the data generated after port 23946 is used, and the data is obtained using strCatTcpPort , and then written into pfile , and finally
ps:fget function
If successful, the function returns the same str parameter.
If the end of the file is reached or no characters have been read
**Simulated execution effect: **When we did not start android_server, the cat /proc/net/tcp |grep :5D8A
command effect was used:
No output
And we used
countermeasures after starting android_server :
Since it is a detection port, then just change the port android_server directly,
use ./android_server -p
the port followed by you
Fourth, round-robin detection
void anti_debugger()
{
pthread_t tid;
pthread_create(&tid,NULL,&anti_debug_thread,NULL);
}
void *anti_debugger_thread(void*data)
{
pid_t pid=getpid();
while(true)
{
check_debugger(pid)
}
}
bool check_debugger(pid_t pid)
{
const int pathSize=256;
const int bufSize=1024;
char path[pathSize];
char line[bufSize];
snprintf(path,sizeof(path)-1,"/proc/%d/status",pid);
bool result =true;
FILE *fp=fopen(path,"rt");
if(fp!=NULL)
{
while(fgets(line,sizeof(line),fp))
{
if(strncmp(line,TRACERPID,TRACERPID_LEN)==0)
{
pid_t tracerPid=0;
sscanf(line,"%*s%d",&tracerPid);
if(!tracerPid)
result =false
break;
}
}
fclose(fp);
}
return result;
}
Analysis : It also detects the pid to determine whether it is 0. If it is not 0, an endless loop is performed. The disadvantage of this method is obviously that it takes up memory, which is generally not common.
Five, fork the child process to debug the parent process
void protect_father()
{
pid_t ppid=getppid();
//获取父进程pid
attach(ppid);
}
void attach(pid_t pid)
{
long err =ptrace(PTRACE_ATTACH,pid,NULL,NULL);
if(err<0)
{
perror("PTRACE_ATTACH");
exit(EXIT_FAILURE);
}
}
Analysis : Since the parent process is debugged by the child process, you can consider debugging its child process directly.
Six, ptrace yourself
void anti_debug01()
{
ptrace(PTRACE_TRACEME,0,0,0);
}
This article has been covered in detail before
to sum up
There are many methods for anti-debugging at the so layer. The most important method is the nop method , dynamic debugging and modifying the return value . It should be noted that many anti-debugging methods are not just pure anti-debugging, but also many Encryption algorithms are linked together, which greatly increases the ability of analysis and anti-debugging.