作者 主題: 請問怎麼取得封包表頭的資料  (閱讀 4735 次)

0 會員 與 1 訪客 正在閱讀本文。

stlee

  • 鑽研的研究生
  • *****
  • 文章數: 817
    • 檢視個人資料
請問怎麼取得封包表頭的資料
« 於: 2007-03-11 19:10 »
請先看一下原碼
在printf("222 接收到使用者的連線要求 fd=%d\n",client_sockfd);
那幾行是目前知道的一個server端漏洞所在
而printf("444 伺服器已取得使用者傳來的字串=%c fd=%d \n",ch,fd);的區段因已可接收到
client端傳來的資料所以在這裡是能掌控範圍內
但步驟222的地方應該就是接收到封包的地方,以惡意侵入角度來說應該就是從這裡侵入才是
所以想用一個"乾淨封包"比對"連線進來的封包"的方式阻絕惡意入侵
在步驟444下面有一個IP迴避機制,因目前是測試階段所以擺在那裡與本主題無關

代碼: [選擇]

int main()
{
  /*socket所需的宣告*/
  int server_sockfd,client_sockfd;
  int server_len,client_len;
  struct sockaddr_in server_address;
  struct sockaddr_in client_address;

  /*執行緒所需的宣告*/
  int res;
  pthread_t a_thread;
  void *thread_result;

  /**/
  char *ipstr;
  int ethmax;
  int ethfoot,ethend;

  char ch;
  int fd;
  int nread;
  int result;
  fd_set readfds,testfds;

  int i,n,k;

  char *c;

  ipstr=(char *)malloc(IPSMAX*IPSLEN);
  ethmax=IPSMAX;
  ethfoot=0;
  ethend=0+(IPSMAX-1);
  /*取得浮動IP*/
  for(i=0;i<ethmax;i++)
    memset(ipstr+(i*IPSLEN),'\0',IPSLEN);
/*  lee_newip(ETHSTR,ethfoot,ethend,ipstr,IPSLEN);/*一次取得全部的IP*/


/**/lee_getaddrl("ppp0",ipstr+(0*IPSLEN),SG_IP);
/**/lee_getaddrl("ppp1",ipstr+(1*IPSLEN),SG_IP);


  /*AF_INET:使用IPv4網路協定;SOCK_STREAM=提供雙向連續且可信賴的資料流,即TCP*/
  server_sockfd = socket(AF_INET,SOCK_STREAM,0);

  /*填寫sockaddr_in結構
  sin_family      為呼叫 socket()時的domain引數,即為AF_xxx的值
  sin_addr.s_addr 為IP位址
  sin_port        為使用的port編號
  */
  server_address.sin_family = AF_INET;
  /*htonl()為將32位元主機字元順序轉成網路字元順序*/
  server_address.sin_addr.s_addr = htonl(INADDR_ANY);
  /*htons()為將16位元主機字元順序轉成網路字元順序*/
  server_address.sin_port = htons(PORT);
  server_len = sizeof(server_address);
  /*對socket定址,建立通訊端*/
  bind(server_sockfd,(struct sockaddr *)&server_address,server_len);

  /*等待連結,建立連結佇列,起始化readfds以處理來自server_sockfd的輸入*/
  listen(server_sockfd,MAXSOCKFD);
  FD_ZERO(&readfds);
  FD_SET(server_sockfd,&readfds);

i=0;
  while(1)
  {
    testfds=readfds;


printf("使用IP:%s 備用IP=%s\n",ipstr+(0*IPSLEN),ipstr+(1*IPSLEN));
printf("111 伺服器等待中:與使用者通訊(已接到使用者傳來的資料)共%d次 \n",i);
i+=1;

    /*select()為:"先等待,直到有東西進來"的方式等待輸入的抵達在這裡是指伺服端將等待
    到使用者端有傳來資料,所以"會停在這裡"一直等到有東西進來
    則如此可避免"忙碌等待"即不斷掃描是否有資料抵達的等待方式(忙碌等待很損耗CPU時間)*/
    result = select(FD_SETSIZE,&testfds,(fd_set *)0,(fd_set *)0,(struct timeval *)0);
    if(result < 1)
    {
      perror("0000000000");
      exit(1);
    }
    for(fd=0; fd < FD_SETSIZE ;fd++)
    {
      if(FD_ISSET(fd,&testfds))
      {

        if(fd == server_sockfd)
        {
/*#################################################################################*/
          client_len = sizeof(client_address);
          client_sockfd = accept(server_sockfd,(struct sockaddr *)&client_address,&client_len);
          FD_SET(client_sockfd,&readfds);

          printf("222 接收到使用者的連線要求 fd=%d\n",client_sockfd);
/*#################################################################################*/

        }
        else
        {
          ioctl(fd,FIONREAD,&nread);
          if(nread == 0)
          {
            close(fd);
            FD_CLR(fd,&readfds);
            printf("333 使用者已離線 fd=%d \n",fd);

          }
          else
          {
            read(fd,&ch,1);
            printf("444 伺服器已取得使用者傳來的字串=%c fd=%d \n",ch,fd);
            /*fd可做為區分是哪一位使用者的旗標值*/

/*建立新執行緒以執行lee_newipt(),要傳遞的參數必須先轉型成void型態*/
/*進行IP迴避*/
if(ch == '!')
{

  shutdown(client_sockfd,2);/*關閉可疑使用者的連線*/

/*  res=pthread_create(&a_thread,NULL,lee_newipt,(void *)ipstr+(1*IPSLEN));
*/
  /*取得浮動IP*/
/*  for(i=0;i<ethmax;i++)
    memset(ipstr+(i*IPSLEN),'\0',IPSLEN);
  lee_newip(ETHSTR,ethfoot,ethend,ipstr,IPSLEN);/*一次取得全部的IP*/

/*lee_runnewip("ppp",0,1);


/**/lee_getaddrl("ppp0",ipstr+(0*IPSLEN),SG_IP);
/**/lee_getaddrl("ppp1",ipstr+(1*IPSLEN),SG_IP);

break;
}
else
{
            if((fd%2) == 1)
              ch++;
            else
              ch='A';

            write(fd,&ch,1);
}

          }/*else END*/
        }/*else END*/
      }/*if(FD_ISSET(fd,&testfds)) END*/
    }/*for(fd=0; fd < FD_SETSIZE ;fd++) END*/

printf("..............................................................................\n");

  }
printf("程式結束\n");
/*pthread_exit(NULL);/*執行緒作用完畢,終止該執行緒*/

}



非常感謝 :D
程式是人寫的,別讓工具的限制成為您想像力的極限
~程式中最重要的部份應該是註解而不是程式碼,這是因為解讀註解一定比解讀程式碼簡單
~程式寫好後約一個月就會忘的差不多了,所以花點時間把註解寫好至少能讓自己(或別人)看的懂當初在寫什麼

stlee

  • 鑽研的研究生
  • *****
  • 文章數: 817
    • 檢視個人資料
請問怎麼取得封包表頭的資料
« 回覆 #1 於: 2007-03-12 02:56 »
在這裡提到一個IP封包的表頭
http://www.study-area.org/2freebsd/
現在的想法是,如果是在data區置入控制命令,雖然可以被入侵,但卻很容易可以檢查出來
因為read(fd,&ch,1);讀取一個byte而client端傳來的也是1byte所以只要逐位元去檢查
或在data區前面置入檢查位元就可以判定是不是正常的(可控制)連線,如果不是則可以啟
動IP迴避機制

但是前面的表頭資料跑哪裡去了???

所以如果能將控制命令植入表頭中,則威力將遠大於置入data區了,因為程式開發人員
比較無法去判讀表頭資料(表頭各項資料寬度不一樣所以必用到位元遮罩及位移)則面對
這種入侵手法將較無抵抗能力

而在read(fd,&ch,1);讀取前一定有一個機制去"剝掉"表頭

在這裡有一樣值得注意的就是read(fd,...);使用的參數fd是一個int型態的"檔案描述詞"
表示他是一個"已開啟的檔案",但以fstst()去取得fd檔案狀態時,其檔案長度的st_size卻
是0,而有一個巨集定義S_ISSOCK(st_mode)表示可檢查該檔案是不是一個socket
那可能就不能以stat()系列去取得該socket檔的狀態(應該也可以,但不知是何函數)


用open()嗯....是可以試試,不過必須注意errno的變化可能較容易除錯,明天再試
(想到東方不敗--->葵花寶典--->欲練神功,必先自宮)
程式是人寫的,別讓工具的限制成為您想像力的極限
~程式中最重要的部份應該是註解而不是程式碼,這是因為解讀註解一定比解讀程式碼簡單
~程式寫好後約一個月就會忘的差不多了,所以花點時間把註解寫好至少能讓自己(或別人)看的懂當初在寫什麼

stlee

  • 鑽研的研究生
  • *****
  • 文章數: 817
    • 檢視個人資料
請問怎麼取得封包表頭的資料
« 回覆 #2 於: 2007-03-14 02:53 »
網路找很久後還是以man -K fd_set找到個好東西

代碼: [選擇]

GETFDS(3PVM)                    PVM Version 3.4                   GETFDS(3PVM)

NAME
       pvm_getfds - Get file descriptors in use by PVM.

SYNOPSIS
       C    int nfds = pvm_getfds( int **fds )

       Fortran   Not Available

PARAMETERS
       fds     Returns integer array of file descriptors.

DESCRIPTION
       A  PVM  task uses sockets to communicate between libpvm and other tasks
       or the pvmd.  It is sometimes useful to know the file  descriptor  num-
       bers  of  the  sockets in order to wait from input from either PVM mes-
       sages or an external source.  For example, the  PVM  console  waits  on
       both  keyboard  input and notify messages.  Input can be multiplexed by
       polling all sources, but this wastes cpu cycles.  Instead, the select()
       system  call can be used to wait until one or more sources of input are
       ready.

       If it completes successfully, pvm_getfds returns the number of  sockets
       in  use,  and  the  file  descriptor numbers in an array (allocated and
       freed by libpvm).  At least one socket  always  exists  (from  task  to
       pvmd),  and  its  descriptor  is  always fds[0].  The number of sockets
       varies as direct routes are established to other tasks.

       It can be difficult to track the set  of  file  descriptors  if  direct
       routing  is  enabled, because routes are created as messages are either
       sent or received.  The simplest approach is to disable direct  routing.

       When  select  returns with a PVM file descriptor ready, a complete mes-
       sage may be ready to be received, or instead only  a  fragment  may  be
       waiting.   pvm_nrecv or pvm_probe should be used test without blocking.

RESTRICTIONS
       pvm_getfds is only available when running PVM on a Unix or similar sys-
       tem.

EXAMPLES
       The  following  program  fragment  waits until either keyboard input is
       available, or a PVM message has arrived.

            int *d;
            fd_set r;

            pvm_setopt(PvmRoute, PvmDontRoute);
            pvm_getfds(&d);

            FD_ZERO(&r);
            FD_SET(0, &r);
            FD_SET(d[0], &r);
            while (1) {
                 if (select(d[0] + 1, &r, (fd_set*)0, (fd_set*)0,
                            (struct timeval*)0) > 0) {
                      if (FD_ISSET(0, &r))
                           ...    /* read keyboard input */
                      if (FD_ISSET(d[0], &r) && pvm_nrecv(-1, -1) > 0)
                           ...    /* got a PVM message */
                 }
            }

ERRORS
       The following error condition can be returned by pvm_getfds:

       PvmSysErr
              pvmd not responding.

SEE ALSO
       pvm_notify(3PVM), pvm_trecv(3PVM)

                                 22 Nov, 1994                     GETFDS(3PVM)

還有附範例,實在是給它有點粉美滿的說......可是英文還是給它看不懂><"
程式是人寫的,別讓工具的限制成為您想像力的極限
~程式中最重要的部份應該是註解而不是程式碼,這是因為解讀註解一定比解讀程式碼簡單
~程式寫好後約一個月就會忘的差不多了,所以花點時間把註解寫好至少能讓自己(或別人)看的懂當初在寫什麼

stlee

  • 鑽研的研究生
  • *****
  • 文章數: 817
    • 檢視個人資料
請問怎麼取得封包表頭的資料
« 回覆 #3 於: 2007-03-14 20:23 »
Fortran   Not Available
不能用@@!
程式是人寫的,別讓工具的限制成為您想像力的極限
~程式中最重要的部份應該是註解而不是程式碼,這是因為解讀註解一定比解讀程式碼簡單
~程式寫好後約一個月就會忘的差不多了,所以花點時間把註解寫好至少能讓自己(或別人)看的懂當初在寫什麼

stlee

  • 鑽研的研究生
  • *****
  • 文章數: 817
    • 檢視個人資料
請問怎麼取得封包表頭的資料
« 回覆 #4 於: 2007-04-10 01:51 »
哈哈....踏破鐵鞋無覓處,得來要費一番大功夫..........

http://phorum.study-area.org/viewtopic.php?p=228306#228306

最近買的一本書裡面有講到.....[第二章](28頁),指出起點與其終點的資料指標與其資料結構

看來真要費一番功夫去研究,但不是要去重新發明輪子而是相信唯有實做過相關的程式處理

才能去更進一步了解網路的啦^^

大家加油^^
程式是人寫的,別讓工具的限制成為您想像力的極限
~程式中最重要的部份應該是註解而不是程式碼,這是因為解讀註解一定比解讀程式碼簡單
~程式寫好後約一個月就會忘的差不多了,所以花點時間把註解寫好至少能讓自己(或別人)看的懂當初在寫什麼