2014-10-17 173 views
0

我有以下代码,我试图用来获取套接字另一端的地址,但getpeername()总是失败,并且出现bad file descriptor错误。我究竟做错了什么?getpeername总是给出错误的文件描述符

#include <arpa/inet.h> 
#include<syscall.h> 
#include<errno.h> 
#include <netinet/in.h> 
#include<string.h> 
#include<sys/socket.h> 
#include<stdio.h> 
#include<sys/ptrace.h> 
#include<sys/types.h> 
#include<sys/wait.h> 
#include<unistd.h> 
#include<sys/user.h> 
#include<sys/syscall.h> /* For SYS_write etc */ 
#include<stdlib.h> 

#define ORIG_RAX 15 
#define SYSCALL_MAXARGS 6 
#define RDI 14 

int main() 
{ 
    //**********declarations and memory allocations**********// 
    ssize_t size; 
    long sys_call_number, temp_long; 
    int status, temp, i, j, k, flag; 

    struct sockaddr_in ip_addr_struct; 
    socklen_t ip_addr_structlen = sizeof(ip_addr_struct); 
    struct user_regs_struct regs; 

    struct sockaddr_in* connect_struct; 

    char* filepath = malloc(1024); 
    char* fdpath = malloc(1024); 
    char* message = malloc(1024); 
    char* connect_ip = malloc(1024); 
    char* ip_addr = malloc(1024); 

    char* temp_char1,* temp_char2; 

    pid_t proc; 

    //**********getting pid and attaching to process**********// 
    scanf("%d",&proc); 

    ptrace(PTRACE_ATTACH,proc, NULL, NULL); 

    //**********starting the trace process**********// 

    //The system call number used in switch() case to determine particular system calls// 
    while(1) 
    { 
      wait(&status); 
      if(WIFEXITED(status)) 
      { 
       printf("****Process exited****\n"); 
       break; 
      } 
       ptrace(PTRACE_GETREGS, proc, NULL, &regs); 
       sys_call_number = regs.orig_rax; 

     switch(sys_call_number) 
     { 
      case 44: 
       printf("sendto\n"); 
       //***printing the register values containing system call parameters***// 
       printf("%llu - %llu - %llu - %llu - %llu - %llu\n", regs.rdi, regs.rsi, regs.rdx, regs.r10, regs.r8, regs.r9); 
       //***getting the peer address***// 
       errno = 0; 
       temp = getpeername(regs.rdi, (struct sockaddr *)&ip_addr_struct, &ip_addr_structlen); 
       if(temp == -1) 
       { 
        printf("error is getpeername-%d-%s\n",temp,strerror(errno)); 
        return -1; 
       } 

       int port = ntohs(ip_addr_struct.sin_port); 
       inet_ntop(AF_INET, &(ip_addr_struct.sin_addr), ip_addr, 1024); 
       printf("%d-%s\n", port, ip_addr); 
       port = 0; 
       //***reading message being send***// 
       temp_char2 = message; 
       j = 0; 
       while(j < (regs.rdx/8)) 
       { 
        temp_long = ptrace(PTRACE_PEEKDATA, proc, regs.rsi + (j*8) , NULL); 
        memcpy(temp_char2, &temp_long, 8); 
        temp_char2 += 8; 
        ++j; 
       } 
       temp_long = ptrace(PTRACE_PEEKDATA, proc, regs.rsi + (j*8) , NULL); 
       memcpy(temp_char2, &temp_long, regs.rdx - (j*8)); 
       message[regs.rdx] = '\0'; 
       printf("Message-%s-\n\n", message); 
      break; 
     } 
    } 
} 

下面是从一个这样的系统调用

sendto 
14 - 32064144 - 884 - 16384 - 0 - 0 
--1-Bad file descriptor 
0-0.0.0.0 
Message-GET /?gfe_rd=cr&ei=2WYzVLCjFq7M8gfLlICoDg HTTP/1.1^M 
User-Agent: NetSurf/2.9 (Linux; x86_64)^M 
Host: www.google.co.in^M 
Accept: */ 
Accept-Encoding: gzip^M 
Cookie:PREF=ID=yu3vtr7i452389b4o236v4t28o37v723tn8vt0783tnv0723p78 N823748923bt87t2387b473287b8273t48 
+0

@nos:但下面的代码在sendto()系统时打印写入'http header'调用被执行,文件描述符如何无效? 我将发布一些输出 – Haris 2014-10-17 07:57:44

+2

无论您的ptrace'ing正在使用的另一个进程的文件描述符是什么,在您的程序中都是无效的,因此也就是错误的文件描述符。 另外,如果其他程序发送的套接字是一个不是connect()的UDP套接字,getpeername()在任何情况下都不会给你任何信息。 – nos 2014-10-17 07:58:36

+0

@nos:我应该如何尝试UDP套接字? – Haris 2014-10-17 08:00:11

回答

1

套接字描述符不是两个过程之间共享的输出。捕获的套接字描述符仅在跟踪过程中有效,在跟踪过程中不起作用。这就是为什么getpeername抱怨坏描述符。
来自ptrace手册:
ptrace()系统调用提供了一种方法,通过该方法,父进程可以观察并控制另一个进程的执行,并检查并更改其核心映像和寄存器。它主要用于实现断点调试和系统调用跟踪。
没有词说他们共享进程空间,因此,他们不能共享套接字描述符,内存地址等。

+0

Thanx,我明白了.. :) – Haris 2014-10-17 09:24:42