PE64位,放入ida进入main函数逻辑很简单,输入flag,base64后进行比较,但是解出来是乱码



进入init数组中发现有函数在执行main前被调用
进入CDA函数发现fork了一个子进程

pid_t fork( void);
(pid_t 是一个宏定义,其实质是int 被定义在#includesys/types.h>中)
返回值: 若成功调用一次则返回两个值,子进程返回0,父进程返回子进程ID;否则,出错返回-1
上述代码中子进程执行ptrace,父进程执行AD7,ptrace是一个系统调用,可以使一个进程调式另一个进程,是gdb核心
#include <sys/ptrace.h>
long ptrace(enum __ptrace_request request, pid_t pid, void *addr, void *data);
- enum __ptrace_request request:指示了 ptrace 要执行的命令。
- pid_t pid:指示 ptrace 要跟踪的进程。
- void *addr:指示要监控的内存地址。
- void *data:存放读取出的或者要写入的数据。
其中request包含
PTRACE_TRACEME | 本进程被其父进程所跟踪。其父进程应该希望跟踪子进程。 |
PTRACE_PEEKTEXT, PTRACE_PEEKDATA | 从内存地址中读取一个字节,内存地址由addr给出。 |
PTRACE_PEEKUSR | 从USER区域中读取一个字节,偏移量为addr。 |
PTRACE_POKETEXT, PTRACE_POKEDATA | 往内存地址中写入一个字节。内存地址由addr给出。 |
PTRACE_POKEUSR | 往USER区域中写入一个字节。偏移量为addr。 |
PTRACE_SYSCALL, PTRACE_CONT | 重新运行,SYSCALL遇到系统调用在遇到系统调用时将控制权给回父进程。 |
PTRACE_KILL | 杀掉子进程,使它退出。 |
PTRACE_SINGLESTEP | 设置单步执行标志 |
PTRACE_ATTACH | 跟踪指定pid 进程。 |
PTRACE_DETACH | 结束跟踪 |
关于ptrace反调试
1.进程如果执行ptrace(PT_DENY_ATTACH, 0, 0, 0);表示拒绝被调试,调试器无法调试该进程
2.当有调试器调试该进程时,执行到ptrace(PTRACE_TRACEME, 0, NULL, NULL)将有父进程调试但是由于一个进程仅能被一个进程调试,该进程已被调试器调试故返回-1结束进程
if (ptrace(PTRACE_TRACEME, 0, NULL, NULL) == -1) {
printf("Debugger detected!\n");
return 1;
}
AD7函数,waitpid函数会等待子进程运行结束或者有信号时返回,将等待进程的状态码保留在stat_loc中,当stat_loc!=127(中断)时退出,在子进程中只执行了ptrace(PTRACE_TRACEME, 0LL, 0LL, 0LL);没有发送任何信号,故AD7函数只是等待子进程退出后自己也退出

父进程没做什么,看子进程
for ( i = 0; i <= 0; ++i )
result = ((sub_55E78000095A + i + 7))(11LL, 13LL, 17LL);
return result;
上述代码确实执行95A+7=961函数

操作的数组离base64码表很近并且BA-3f=5f正好对应base64码表,故在换码表


看init数组中的第二个函数执行95A+BF=A19改编码后的值


程序逻辑
父进程------->等待子进程结束后退出
子进程-------->改码表和编码值后进入main函数进行输入编码比较
故我们可以将此处nop掉得到单进程版本调试


就可以看到真实的码表和编码值


Comments NOTHING