---[ Phrack Magazine Volume 7, Issue 51 September 01, 1997, article 11 of 17 -------------------------[ The Art of Port Scanning --------[ Fyodor ¹ø¿ª: ±¤ÁÖ ÇØÄ¿½º·¦ [Techniques] Á¤°è¿Á(hook7346@kornet.net) [Feature] È«»ó±¹(scrude@orgio.net) [Abstract][Introduction][The Code]·ù¼ºÃ¶(oprix@hanmail.net) [¿ä¾à] Abstract ÀÌ ¹®¼­´Â ¾î´À ¼­¹öÀÇ ¾î´À Æ÷Æ®(ÇÁ·ÎÅäÄÝÀÇ Ãß»óÈ­¿Í ºñ½ÁÇÑ °³³ä)°¡ ¿­·È´ÂÁö ¸¦ È®ÀÎÇÏ´Â ±â¼úÀ» ¸»ÇÑ´Ù. Æ÷Æ®´Â Á¤º¸ ±³·ù¸¦ À§ÇÑ ±âÃÊ°¡ µÈ´Ù. ÀÌ Á¸À縦 ¾Æ´Â °Ç ¼­¹ö¿Í Á¤º¸¸¦ ±³È¯Çϴµ¥ À¯¸®ÇÏ´Ù. µû¶ó¼­ ÀÌ·± ³×Æ®¿öÅ© ȯ°æÀ» °Ë»öÇÏ·Á´Â »ç¶÷µé¿¡°Õ ƯÈ÷ ÇØÄ¿¿¡°Õ ¾ÆÁÖ À¯¿ëÇÑ ±â¼úÀÌ´Ù. ¿©·¯ ¸Åü¿¡¼­ ¶°µå´Â µ¥ ºñÇؼ­ ÀÎÅͳÝÀº TCP 80Æ÷Æ®·Î¸¸ ÀÌ·ç¾îÁø°Ô ¾Æ´Ï´Ù. WWW·Î¸¸ ¸ðÀº Á¤º¸¸¦ »ç¿ëÇÏ´Â »ç¶÷ÀÌ ÀÖ´Ù¸é ±×»ç¶÷Àº º¸Åë½Ç·ÂÀÇ AOL »ç¿ëÀÚ¿Í °°Àº ¼öÁØÀÏ »ÓÀÌ´Ù. ¶Ç ÀÌ ¹®¼­´Â ³»°¡ ¼ÓÇÑ ÇÁ·Î±×·¥À» ¸¸µå´Â ÇÁ·ÎÁ§Æ®ÀÇ ¹®¼­¸¦ ¼Ò°³ÇÏ´Â Àǹ̵µ ÀÖ´Ù. ±× ÇÁ·Î±×·¥Àº °Å´ë ³×Æ®¿öÅ©¸¦ °Ë»çÇÒ¶§³ª ´Ù¸¥ ½ºÄ³³Ê¸¦ ¾µ¶§ ¸Â´Ú¶ß¸®´Â ¹®Á¦¸¦ ÇØ°áÇÑ Æ÷Æ® ½ºÄ³³ÊÀÌ´Ù. À̸§Àº nmapÀ̶ó°í ÇÏ°í ¾Æ·¡ÀÇ ±â¼úÀ» ¾µ ¼ö ÀÖ´Ù. - vanilla TCP connect() scanning, - TCP SYN (half open) scanning, - TCP FIN (stealth) scanning, - TCP ftp proxy (bounce attack) scanning - SYN/FIN scanning using IP fragments (bypasses packet filters), - UDP recvfrom() scanning, - UDP raw ICMP port unreachable scanning, - ICMP scanning (ping-sweep), and - reverse-ident scanning. ¾Æ·¡ÀÇ ¼Ò½º ÄÚµå´Â ÀÚÀ¯½º·´°Ô ¹èÆ÷Çصµ ÁÁ´Ù. [¼Ò°³] Introduction ¿ªÀÚ ¿Ð: ¿Ö À̺κп¡ À̱ÛÀÌ µé¾î°¬´ÂÁö ¸ð¸£°Ú´Ù. ÀúÀÚ ³ÌµÎ¸®ÀÎµí ½Í´Ù. ±ÍÂú¾Æ¼­ ¹ø¿ªÀº ÇÇÇß´Ù. Scanning, as a method for discovering exploitable communication channels, has been around for ages. The idea is to probe as many listeners as possible, and keep track of the ones that are receptive or useful to your particular need. Much of the field of advertising is based on this paradigm, and the "to current resident" brute force style of bulk mail is an almost perfect parallel to what we will discuss. Just stick a message in every mailbox and wait for the responses to trickle back. Scanning entered the h/p world along with the phone systems. Here we have this tremendous global telecommunications network, all reachable through codes on our telephone. Millions of numbers are reachable locally, yet we may only be interested in 0.5% of these numbers, perhaps those that answer with a carrier. The logical solution to finding those numbers that interest us is to try them all. Thus the field of "wardialing" arose. Excellent programs like Toneloc were developed to facilitate the probing of entire exchanges and more. The basic idea is simple. If you dial a number and your modem gives you a CONNECT, you record it. Otherwise the computer hangs up and tirelessly dials the next one. While wardialing is still useful, we are now finding that many of the computers we wish to communicate with are connected through networks such as the Internet rather than analog phone dialups. Scanning these machines involves the same brute force technique. We send a blizzard of packets for various protocols, and we deduce which services are listening from the responses we receive (or don't receive). [±â¼úÀûÀÎ ³»¿ëµé] Techniques Áö±Ý±îÁö, ¸ñÇ¥¼­¹ö(°ø°ÝÇÏ°íÀÚ ÇÏ´Â ¼­¹ö)°¡ »ç¿ëÇÏ¸ç ¿­°íÀÖ´Â ÇÁ·ÎÅäÄÝ°ú Æ÷Æ®µéÀ» °Ë»ç Çϱâ À§ÇÑ ¼ö¸¹Àº ±â¼úµéÀÌ ¹ßÀüÇØ ¿Ô´Ù. ±× ±â¼úµéÀº °¢±â ÀåÁ¡°ú ´ÜÁ¡À» °¡Áö°í ÀÖ´Ù. ÀÌÁ¦ºÎÅÍ °¡Àå ÀϹÝÀûÀÎ °ÍµéÀ» ³ª¿­ÇØ º¸°Ú´Ù. - TCP connect() ½ºÄ³´× : ÀÌ°ÍÀº TCP ½ºÄ³´×Áß¿¡¼­ °¡Àå ±âº»ÀûÀÎ ¸ðÇüÀÌ´Ù. O/S(¿î¿µÃ¼ Á¦)°¡ Á¦°øÇÏ´Â connect() ½Ã½ºÅÛ ÄÝÀº ¼­¹öÀÇ °¢±â Àß ¾Ë·ÁÁø Æ÷Æ®·Î Á¢¼ÓÇϱâ À§Çؼ­ »ç¿ëµÈ´Ù. ¸¸¾à, ±×·¯ÇÑ Æ÷Æ®°¡ ¿­·ÁÁ® ÀÖ´Ù¸é, connect() ½Ã½ºÅÛ ÄÝÀº Á¤»óÀûÀ¸·Î µ¿À۵ȴÙ. ±×·¯³ª, Æ÷Æ®°¡ ´ÝÇô ÀÖÀ¸¸é, ±× Æ÷Æ®´Â µµ´ÞÇÒ ¼ö ¾ø´Â °ÍÀ¸·Î ÆǸíµÈ´Ù. ÀÌ TCP connect() ½ºÄ³´×ÀÇ ÇϳªÀÇ °­Á¡Àº ÀÌ ½Ã½ºÅÛ ÄÝÀ» ´©±¸³ª »ç¿ëÇÒ ¼ö ÀÖ´Ù´Â °ÍÀÌ ´Ù. À¯´Ð½º½Ã½ºÅÛÀ» »ç¿ëÇÏ´Â ¸ðµç »ç¿ëÀÚ´Â ÀÌ ½Ã½ºÅÛ ÄÝÀ» ÀÌ¿ëÇÒ ¼ö ÀÖ´Ù. ¶Ç ÇϳªÀÇ ÀÌ Á¡Àº ¼Óµµ´Ù. °¢°¢ÀÇ ¸ñÇ¥ Æ÷Æ®¿¡ µ¶¸³ÀûÀÎ connect() ÄÝÀ» ÀϷĹæ½ÄÀ¸·Î ¸¸µç´Ù¸é, ´À¸° Á¢¼Ó¿¡ ²Ï ¸¹Àº ½Ã°£ÀÌ °É¸± °ÍÀÌÁö¸¸, ¿ì¸®´Â º´·Ä¹æ½ÄÀ¸·Î ¸¹Àº Socket( connect()ÄÝÀÇ Á¢¼Ó»óÅ )À» ÀÌ¿ëÇÏ¿© ½ºÄµÀ» ºü¸£°Ô ¼öÇàÇÒ ¼ö ÀÖ´Ù. non-blocking I/O¸¦ ÀÌ¿ëÇϸé, ªÀº time-out period(.Á¦Çѽð£)¸¦ ¼³Á¤ÇÏ°í, ÇѲ¨¹ø¿¡ ¸ðµç SocketµéÀÇ »óŸ¦ º¼ ¼ö ÀÖ´Ù. ÀÌ°ÍÀº NMAPÀÌ Áö¿øÇÏ´Â °¡Àå ºü¸¥ ½ºÄ³´×¹æ¹ýÀ̸ç, -t ¿É¼ÇÀ» ¾²¸é »ç¿ëÇÒ ¼ö ÀÖ´Ù. ÀÌ ¹æ½ÄÀÇ Å©³ªÅ« ¾àÁ¡Àº ½±°Ô ¹ß°¢µÇ°í ÇÊÅ͸µµÈ´Ù´Â °ÍÀÌ´Ù. ¸ñÇ¥¼­¹ö´Â connect() ÄÝÀÇ Á¢¼ÓÀ» ¹ÞÀº ¼­ºñ½º¸¦ ÅëÇؼ­ ¸¹Àº ¾çÀÇ Á¢¼Ó ¹× ¿¡·¯¸Þ½ÃÁö°¡ ·Î±×¿¡ ±â·ÏµÇ¸é ¹Ù·Î Á¢¼ÓÀ» ²÷À» °ÍÀÌ´Ù. - TCP SYN ½ºÄ³´× : ÀÌ ±â¼úÀº Åë»ó "half-open"(¹Ý¸¸ ¿­·ÁÁø)½ºÄ³´×À¸·Î ºÒ·ÁÁø´Ù. ¿Ö³Ä ÇÏ¸é ¿Ïº®ÇÑ TCP ¿¬°áÀ» ÇÏÁö ¾Ê±â ¶§¹®ÀÌ´Ù. ¿©·¯ºÐÀº ½ÇÁ¦·Î Á¢¼ÓÀ» ÇÏ·Á´Â °Íó·³ SYN ÆÐŶÀ» º¸³»°í, ÀÀ´äÀ» ±â´Ù¸°´Ù. SYN|ACK ÀÀ´äÀº Æ÷Æ®°¡ ¿­·ÁÁ® ÀÖÀ½À» °¡¸®Å²´Ù. RST ÀÀ´äÀº Æ÷Æ®°¡ ´ÝÇôÁ® ÀÖÀ½À» °¡¸®Å²´Ù. ¸¸¾à, SYN|ACK ÀÀ´äÀÌ ¿À¸é, ¿©·¯ºÐÀº Áï½Ã RST ÀÀ´äÀ» º¸³»¾î connect() Á¢¼ÓÀ» ²÷´Â´Ù. (½ÇÁ¦·Î´Â kernelÀÌ ¿ì¸®¸¦ À§Çؼ­ ÀÌ ÀÛ¾÷À» ´ë ½ÅÇØ ÁØ´Ù.) ÀÌ ½ºÄ³´× ±â¼úÀÇ ÀÌÁ¡Àº ÀϺΠ»çÀÌÆ®µé¸¸ÀÌ ÀÌ·± Á¢¼Ó»óȲÀ» ·Î±×ÆÄÀÏ¿¡ ±â·ÏÇÑ´Ù´Â °ÍÀÌ ´Ù. ( ¿ªÀÚÁÖ: ÀÌ ¹®¼­°¡ ¾²¿©Áú ¶§´Â ±×·¨´ÂÁö ¸ð¸£Áö¸¸, ÀÌ ±ÛÀ» Çؼ®ÇÏ´Â Áö±ÝÀº ¾È ±× ·² °ÍÀÌ´Ù.) ºÒÇàÈ÷µµ, ÀϹÝÀûÀÎ SYN ÆÐŶÀ» ¸¸µé±â À§Çؼ­´Â root °ü¸®ÀÚÀÇ ±ÇÇÑÀ» °¡Á®¾ß ÇÑ´Ù. SYN ½ºÄ³´×À» ÇÏ·Á¸é NMAP¿¡¼­ -s ¿É¼ÇÀ» »ç¿ëÇÏ¸é µÈ´Ù. - TCP FIN ½ºÄ³´× : ÀÌÁ¦´Â SYN ½ºÄ³´×Á¶Â÷ ´õ ÀÌ»ó ºñ¹Ð½º·¯¿î °ÍÀÌ ¾Æ´Ï´Ù. ¾î¶² firewall µé°ú packet filterµéÀº ¿­·ÁÁ® ÀÖÁö ¾ÊÀº Æ÷Æ®µé¿¡ Á¢±ÙÇÏ´Â SYN ÆÐŶµéÀ» °¨½ÃÇÑ ´Ù. ±×¸®°í, synlogger¿Í Courtney °°Àº ÇÁ·Î±×·¥ ¶ÇÇÑ, ÀÌ·± SYN ½ºÄµÀ» °¨ÁöÇÒ ¼ö ÀÖ´Ù. ¹Ý¸é¿¡, FIN ÆÐŶÀº ±×·¯ÇÑ ¹æÇظ¦ ¶ÕÀ» ¼ö ÀÖ´Ù. ÀÌ ½ºÄ³´× ±â¼úÀº Phrack 49ÀÇ 15¹ø ¹® ¼­·Î½á Uriel Maimon¿¡ ÀÇÇؼ­ ÀÚ¼¼È÷ ¼³¸íµÇ¾î ÀÖ´Ù. ´ÝÇôÁø Æ÷Æ®µéÀº FIN ÆÐŶ¿¡ RST·Î ÀÀ´äÇÏ´Â °æÇâÀÌ ÀÖ´Ù. ¿­·ÁÁø Æ÷Æ®µéÀº FIN ÆÐŶÀ» ¹« ½ÃÇÑ´Ù. ÀÌ°ÍÀº TCP ¿î¿ë¿¡¼­ÀÇ ÇϳªÀÇ bugÀ̸ç, 100% ½Å·ÚÇÒ ¼ö ¾ø´Ù. ( ¾î¶² ½Ã½ºÅÛµé, ƯÈ÷ Micro$oft ¿î¿µÃ¼Á¦ »ç¿ë¼­¹öµé, Àº ÀüÇô ¹ÝÀÀÀ» º¸ÀÌÁö ¾Ê´Â´Ù.) ÀÌ ±â¼úÀº ´ëºÎºÐÀÇ ´Ù¸¥ ½Ã½ºÅÛ¿¡¼­´Â ¾ÆÁÖ Àß µ¿ÀÛÇÑ´Ù. FIN ½ºÄ³´×Àº NMAP¿¡¼­ -U ¿É¼ÇÀ¸·Î »ç¿ëµÈ´Ù. - Fragmentation ½ºÄ³´× : ÀÌ°ÍÀº º»ÁúÀûÀ¸·Î ÀüÇô »õ·Î¿î ±â¼úÀÌ ¾Æ´Ñ ´Ù¸¥ ±â¼úµéÀÇ º¯ ÇüµÈ ÇüÅÂÀÌ´Ù. ¿©·¯ºÐÀº ´Ü¼øÈ÷ ŽÁöÆÐŶÀ» º¸³»´Â °ÍÀÌ ¾Æ´Ï¶ó ÆÐŶÀ» ¸î °³ÀÇ ÀÛÀº IP fragment·Î ³ª´«´Ù. ¿©·¯ºÐÀº ¿©·¯ºÐÀÌ ÇÏ°íÀÚ ÇÏ´Â ÀÛ¾÷À» packet filterµéÀ̳ª ´Ù¸¥ °Íµé ÀÌ °¨ÁöÇÏÁö ¸øÇϵµ·Ï TCP Çì´õ¸¦ ¸î °³ÀÇ ÆÐŶÀ¸·Î ºÐ¸®½ÃŲ´Ù. ÁÖÀÇÇϱ⠹ٶõ´Ù!! ¾î¶² ÇÁ·Î±×·¥µéÀ» ÀÌ·¯ÇÑ ¾ÆÁÖ ÀÛÀº ÆÐŶÀ» ´Ù·ç´Âµ¥ ¹®Á¦°¡ ¹ß»ýÇÑ´Ù. ³»(Fyodor)°¡ ¾Ö¿ëÇÏ´Â ½º´ÏÆÛ(sniffer)´Â 24byte ÆÐŶÀÌ ¿Â ÈÄ¿¡ ù ¹ø°·Î ¿À´Â 36byte fragment¸¦ ÀνÄÇÏÁö ¸øÇÑ´Ù. ÀÌ ¹æ¹ýÀÌ ¸ðµç IP fragmentµéÀ» Å¥(Queue : Á÷·ÄÇüÀÇ ¹öÆÛ)¿¡ ÀúÀåÇÏ´Â packet filter³ª firewallÀ» Åë°úÇÏÁö ¸øÇÏ´õ¶óµµ, ¼ö¸¹Àº ³×Æ®¿öÅ©µéÀº ÀÌ·¯ÇÑ fragmentµé¿¡ ´ëÇÑ Á¤º¸¸¦ Á¶ »çÇÒ ¸¸ÇÑ ¿©À¯°¡ ¾ø´Ù. ÀÌ Æ¯Â¡Àº ½ºÄ³³Ê¶ó°í ºÒ¸®¿ì´Â ÇÁ·Î±×·¥µé »çÀÌ¿¡¼­´Â ¾à°£Àº »ý¼ÒÇÑ °ÍÀÌ´Ù. (ÀÌ·¯ÇÑ ±â ´ÉÀ» ÇÏ´Â ½ºÄ³³Ê¸¦ ³ª(Fyodor)´Â ¾ÆÁ÷ º¸Áö ¸øÇß´Ù.) ÀÌ ±â´ÉÀ» ÃßõÇØ ÁØ daemon9¿¡°Ô °¨»çÇÑ´Ù. "-f"¿É¼ÇÀ» »ç¿ëÇϸé, ÁöÁ¤µÈ SYN ¶Ç´Â FIN ½ºÄµ¿¡°Ô ¾ÆÁÖ ÀÛÀº fragment·Î ºÐÇÒµÈ ÆÐŶ À» º¸³»µµ·Ï ÇÒ ¼ö ÀÖ´Ù. - TCP ¿ª ident ½ºÄ³´× : 1996³â ¹ö±×Æ®·¢(bugtraq)¿¡¼­ Dave Goldsmith°¡ ¹ßÇ¥Çß´ø °Í°ú °°ÀÌ ident ÇÁ·ÎÅäÄÝ(RFC1413)Àº ¼³»ç ¾î¶² ÇÁ·Î¼¼½º(ÇÁ·Î±×·¥)°¡ Á¢¼ÓÀ» ÃʱâÈ­ÇÏÁö ¾Ê¾Ò ´õ¶óµµ, TCP¹æ½ÄÀ¸·Î Á¢¼ÓµÈ ±× ÇÁ·Î¼¼¼­ÀÇ ½ÇÇà±ÇÀÚ usernameÀ» °ø°³½ÃÄÑ ¹ö¸°´Ù. ¿¹¸¦ µé¾î¼­, ¿©·¯ºÐÀº httpÆ÷Æ®·Î Á¢¼ÓÇÏ°í, identd¸¦ ÀÌ¿ëÇÏ¿© ¼­¹ö°¡ root ±ÇÇÑÀ¸·Î ½ÇÇàµÇ°í ÀÖ´ÂÁö¸¦ ¾Ë ¼ö ÀÖ´Ù. ÀÌ ½ºÄ³´×Àº ¿ÀÁ÷ »ó´ë¼­¹ö¿ÍÀÇ ¿ÏÀüÇÑ TCP Á¢¼Ó»óÅ¿¡¼­¸¸ °¡´ÉÇÏ ´Ù.("-t" ¿É¼ÇÀ» ¹Ýµå½Ã ½á¾ßÇÑ´Ù´Â °ÍÀ» ÀǹÌÇÑ´Ù.) NMAPÀÇ "-i"¿É¼ÇÀ» ¸ðµç ¿­·ÁÁø Æ÷Æ®ÀÇ ¼ÒÀ¯±ÇÀÚ¸¦ ¹àÇô³»´Âµ¥ ¾²ÀδÙ. - FTP bounce attack : ftp ÇÁ·ÎÅäÄÝ(RFC959)ÀÇ Èï¹Ì·Î¿î Ư¡Àº Proxy ftp Á¢¼Ó(´ë¸® ftp Á¢¼Ó)À» Áö¿øÇÑ´Ù´Â °ÍÀÌ´Ù. ½±°Ô ¸»Çϸé, ¿ì¸®´Â evil.com À̶ó´Â ¼­¹ö¿¡¼­ target.comÀÇ FTP Server-PI(ÇÁ·ÎÅäÄÝ Çؼ®±â)·Î Á¢¼ÓÇÒ ¼ö ÀÖ´Ù. ±×·¯¸é ¿ì¸®´Â Server-PI°¡ Server-DTP(ÀÚ·áÀü¼Û ÇÁ·Î¼¼¼­)¸¦ ÃʱâÈ­½ÃÅ°°í, ÀÎÅͳݰú ¿¬°áµÈ ¾î¶² °÷À¸·Îµç ÆÄÀÏÀ» º¸³¾ ¼ö ÀÖµµ·Ï ÇÒ ¼ö ÀÖ´Ù. ºñ·Ï RFC¿¡¼­ ÇϳªÀÇ ¼­¹ö·ÎºÎÅÍ ´Ù¸¥ ¼­¹ö·Î ÆÄÀÏÀ» Àü¼ÛÇÏ´Â °ÍÀÌ Çã¿ëµÈ´Ù°í ¸í¹éÇÏ°Ô ¸í½ÃÇÏ¿´Áö¸¸, User-DTPµµ ¾Æ¸¶ °¡´ÉÇÒ °ÍÀÌ´Ù. 1985³â¿¡ RFC°¡ óÀ½ Á¦Á¤µÇ¾úÀ» ¶§, ÀÌ°ÍÀº ¸Å¿ì Àß µ¿ÀÛÇÏ¿´Áö¸¸, Áö±Ý ¿ì¸®´Â »ç¶÷µéÀÌ ftp¼­¹ö¸¦ °­Å»ÇÏ°í, µ¥ÀÌÅ͸¦ ÀÎÅͳÝÀÇ ÀÓÀÇÁöÁ¡À¸·Î À¯Ãâ½ÃÅ°´Â °ÍÀ» Çã¿ëÄ¡ ¾Ê´Â´Ù. 1995³â¿¡ *Hobbit*´Â FTP ÇÁ·ÎÅäÄÝÀÇ ÀÌ ¾àÁ¡ÀÌ "µµ´ÞÇÒ ¼ö ¾ø´Â À̸ÞÀÏÀ̳ª news¸¦ °¡»ó ÀûÀ¸·Î Àü¼ÛÇϰųª, ¿©·¯ »çÀÌÆ®ÀÇ ¼­¹öµéÀ» ÀÚ²Ù °Çµé°Å³ª, µð½ºÅ©¸¦ ä¿ì°Å³ª, ¹æÈ­º®À» ¶Ù¾î³Ñµµ·Ï ½ÃµµÇϰųª, Åë»ó µ¿½Ã¿¡ ÃßÀûÇϱ⠳­Ã³ÇÏ°í ¾î·Æ°Ô ¸¸µå´Âµ¥ »ç¿ëµÉ ¼ö ÀÖ´Ù" ¶ó°í ±â¼úÇß´Ù. ¿ì¸®°¡ ÀÌ°ÍÀ» ÀÌ¿ëÇÏ°Ô µÈ ÀÌÀ¯´Â ³î¶ø°Ôµµ proxy ftp ¼­¹öÀÇ TCP Æ÷Æ®µéÀ» ½ºÄµÇϱâ À§ Çؼ­ÀÌ´Ù. ÀÌ·± ½ÄÀ¸·Î, ¿©·¯ºÐÀº ¹æÈ­º®µÚÀÇ ftp¼­¹ö¿¡ Á¢¼ÓÇÒ ¼ö ÀÖ°Ô µÈ´Ù. ±×¸®°í´Â, ¹æ È­º®À¸·Î °¡·ÁÁ® ÀÖ´Â µíÇÑ (139Æ÷Æ®°¡ ¾ÆÁÖ ÁÁÀº ¿¹ÀÌ´Ù.) Æ÷Æ®µéÀ» ½ºÄµÇÑ´Ù. ¸¸¾à, ftp¼­¹ö°¡ ¾î´À ÇÑ µð·ºÅ丮(¿¹¸¦ µé¾î, /incoming µð·ºÅ丮)¿¡ Àб⠶Ǵ ¾²±â ±ÇÇÑ À» Çã¿ëÇÏ°í ÀÖ´Ù¸é, ¿©·¯ºÐÀº ¹Ì¸® ã¾Æ³õÀº ¿­·ÁÁø Æ÷Æ®µé·Î ÀÓÀÇÀÇ µ¥ÀÌÅ͸¦ Àü¼ÛÇÒ ¼ö ÀÖ´Ù. Æ÷Æ® ½ºÄ³´×¿¡ À־, ¿ì¸®ÀÇ ±â¼úÀº ¼öµ¿ÀûÀÎ "user-DTP"°¡ ƯÁ¤Æ÷Æ®·Î ÀÀ´ä´ë±âÁßÀÌ´Ù. ¶ó°í Á¤ÀÇÇϱâ À§Çؼ­ PORT ¸í·É¾î¸¦ »ç¿ëÇÑ´Ù. ±×¸®°í, ¿ì¸®´Â ÇöÀç µð·ºÅ丮¸¦ LIST ÇØ º¸·Á°í ½ÃµµÇÑ´Ù. ±×·¯¸é, °á°ú´Â server-DTP ä³ÎÀ» ÅëÇÏ¿© º¸³»Áø´Ù. ¸¸¾à ¿ì¸®ÀÇ ¸ñÇ¥¼­ ¹ö°¡ ƯÁ¤Æ÷Æ®¿¡ ÀÀ´ä´ë±âÁßÀ̶ó¸é, Àü¼ÛÀº Á¤»óÀûÀ¸·Î ¼öÇàµÉ °ÍÀÌ´Ù. (150 ¶Ç´Â 226 ÀÀ´ä À» »ý¼ºÇϸ鼭...) ±×·¸Áö ¾ÊÀ¸¸é, ¿ì¸®´Â "425 µ¥ÀÌÅÍÁ¢¼ÓÀ» »ý¼ºÇÒ ¼ö ¾ø½À´Ï´Ù. Á¢¼Ó°ÅºÎ" ¶ó´Â ¸Þ½ÃÁö¸¦ ¹ÞÀ» °ÍÀÌ´Ù. ±×¸®°í ³­ ÈÄ, ¿ì¸®´Â ¶Ç ´Ù¸¥ PORT ¸í·ÉÀ» ³»·Á¼­ ´ÙÀ½ Æ÷Æ® ¸¦ ½ÃÇèÇØ º»´Ù. ÀÌ ¹æ½ÄÀÇ ÁÁÀº Á¡Àº ¾ÆÁÖ È®½ÇÇÏ´Ù´Â °ÍÀÌ´Ù. (ÃßÀûÇϱ⠾î·Æ°í, ¹æÈ­º®À» Åë°úÇÒ °¡´É¼º ÀÌ ÀÖ´Ù.) ´ÜÁ¡Àº ¼Óµµ°¡ ´À¸®°í, ¾î¶² FTP ¼­¹öµéÀº proxy±â´ÉÀ» »ç¿ëÇÒ ¼ö ¾øµµ·Ï ¸¸µé¾î ³õ¾Ò°í, ÀÌ¹Ì ¹æ¾îÃ¥À» ¸¸µé¾î ³õ¾Ò´Ù. ÀÌ ¹æ½ÄÀÌ À¯¿ëÇÑ°¡¸¦ ¹àÈ÷±â À§Çؼ­ ÀÌ ¹æ½ÄÀÌ µ¿ÀÛÇÏ°í ÇÏ Áö ¾Ê´Â »çÀÌÆ®µéÀÇ ÃÖÃÊÈ­¸é Á¦¸ñ(Banner)À» ¸î°¡Áö ³ª¿­ÇØ º¸¾Ò´Ù. *Bounce attacks worked:* 220 xxxxxxx.com FTP server (Version wu-2.4(3) Wed Dec 14 ...) ready. 220 xxx.xxx.xxx.edu FTP server ready. 220 xx.Telcom.xxxx.EDU FTP server (Version wu-2.4(3) Tue Jun 11 ...) ready. 220 lem FTP server (SunOS 4.1) ready. 220 xxx.xxx.es FTP server (Version wu-2.4(11) Sat Apr 27 ...) ready. 220 elios FTP server (SunOS 4.1) ready *Bounce attack failed:* 220 wcarchive.cdrom.com FTP server (Version DG-2.0.39 Sun May 4 ...) ready. 220 xxx.xx.xxxxx.EDU Version wu-2.4.2-academ[BETA-12](1) Fri Feb 7 220 ftp Microsoft FTP Service (Version 3.0). 220 xxx FTP server (Version wu-2.4.2-academ[BETA-11](1) Tue Sep 3 ...) ready. 220 xxx.unc.edu FTP server (Version wu-2.4.2-academ[BETA-13](6) ...) ready. 'x'·Î Ç¥½ÃµÈ °ÍÀº ÇãÁ¡ÀÌ ÀÖ´Â ¼­¹öµéÀ» º¸È£Çϱâ À§ÇÔÀÌÁö¸¸, ´Ü¼øÈ÷ ÇÑ ÁÙ¿¡ ¸ÂÃß±â À§ÇØ ¼­ ¹®ÀÚ¼ö¸¦ ÁÙÀÎ °ÍÀ¸·Î º¸¸é µÈ´Ù. ¿©·¯ °³ÀÇ '.'µµ °°Àº ¸ñÀûÀ¸·Î ¾²¿´´Ù. bounce attackÀº -b ¿É¼ÇÀ¸·Î NMAP¿¡¼­ »ç¿ëµÈ´Ù. proxy_server´Â ÀϹÝÀû ÀÎ URL Çü½ÄÀ¸·Î Ç¥½ÃµÉ ¼ö ÀÖ´Ù. username:passwd@server:portÀÇ Çü½Ä. ¶ÇÇÑ, ¼­¹ö¿¡ µû ¶ó ¾à°£¾¿ ´Ù¸£Áö¸¸ ¾î¶² Çü½ÄÀÌµç °¡´ÉÇÏ´Ù. - UDP ICMP Æ÷Æ® µµ´ÞºÒ´É ½ºÄ³´× : ÀÌ ½ºÄ³´×¹æ¹ýÀº TCP ´ë½Å UDP¸¦ »ç¿ëÇÑ´Ù´Â Á¡¿¡ ¼­ ¾Õ¿¡ ³ª¿­µÈ ¹æ¹ýµé°ú ±¸º°µÈ´Ù. UDP ÇÁ·ÎÅäÄÝÀÌ °£´ÜÇѵ¥ ¹ÝÇÏ¿©, ¿ÀÈ÷·Á UDP¸¦ ÀÌ¿ë ÇÑ ½ºÄ³´×Àº ¹«Ã´ ¾î·Æ´Ù. ¿Ö³ÄÇϸé, ¿­·ÁÁø Æ÷Æ®µéÀº ¿ì¸®ÀÇ Å½Áö¿¡ Á¤»óÀûÀÎ ÀÀ´äÀ» ÇÏÁö ¾Ê°í, ´ÝÇôÁø Æ÷Æ®µéÀº ¿¡·¯ÆÐŶÀ» ÀÀ´äÇϵµ·Ï ¿ä±¸¹ÞÁö ¾Ê±â ¶§¹®ÀÌ´Ù. ¿î ÁÁ°Ôµµ, ´ëºÎºÐ ÀÇ ¼­¹öµéÀº ¿©·¯ºÐÀÌ ´ÝÇôÁø UDPÆ÷Æ®·Î ÆÐŶÀ» º¸³»¸é ICMP_PORT_UNREACH¿¡·¯¸¦ ¹Ý µå½Ã º¸³½´Ù. ±×·¯¹Ç·Î, Æ÷Æ®°¡ ¿­·ÁÁ® ÀÖÁö ¾Ê´ÂÁö¸¦ ¾Ë ¼ö ÀְԵǰí, ¿ªÀ¸·Î »ý°¢ÇÏ¸é ¾î ¶² Æ÷Æ®µéÀÌ ¿­·ÁÁ® ÀÖ´ÂÁö¸¦ ÆÇ´ÜÇÒ ¼ö ÀÖ´Ù. UDPÆÐŶµé°ú ICMP ¿¡·¯µéÀº µµÂøÇÑ´Ù´Â º¸ ÀåÀÌ ¾ø´Ù. ±×·¡¼­, ÀÌ ºÎ·ùÀÇ UDP½ºÄ³³ÊµéÀº ¹Ýµå½Ã ¼Õ½ÇµÉ °Í °°Àº ÆÐŶµéÀÇ ÀçÀü¼ÛÀ» ¼öÇàÇØ¾ß ÇÑ´Ù. ( ±×·¸Áö ¾Ê´Â´Ù¸é, ¿©·¯ºÐÀº ¾öû³­ ¾çÀÇ À߸øµÈ °á°ú¸¦ ¾ò°Ô µÉ °ÍÀÌ´Ù.) ¶ÇÇÑ, ÀÌ ½ºÄ³´× ±â¼úÀº RFC1812ÀÇ section 4.3.2.8À» Ãæ½ÇÈ÷ µû¸£°í, ICMP ¿¡·¯¸Þ½ÃÁöÀÇ ºñÀ²À» Á¦ÇÑÇÏ´Â ¼­¹öµéÀÇ º¸Á¤ÀÛ¾÷À» Çϱ⠶§¹®¿¡ ´À¸®´Ù. ½ÇÁ¦·Î ¸®´ª½º Ä¿³Î( net/ipv4/icmp.h ÆÄÀϾȿ¡ ÀÖ´Â... )Àº 4ÃÊ´ç 80°³·Î ¸ñÀûÁö µµ´ÞºÒ´É ¸Þ½ÃÁö ¹ß»ýÀ» Á¦ÇÑÇÑ´Ù. °Ô´Ù°¡, ½Ã°£À» ³Ñ°åÀ» °æ¿ì¿¡´Â 1/4ÃÊ°£ÀÇ ÈÞÁö±â°£(½¬´Â ½Ã°£)À» °¡Áø´Ù. ¾ðÁ¨°¡, ³ª´Â ÀÌ°ÍÀ» °¨ÁöÇϱâ À§Çؼ­ º¸´Ù ³ªÀº ¾Ë°í¸®ÁòÀ» NMAP¿¡ Ãß°¡ÇÒ °ÍÀÌ´Ù. ¶ÇÇÑ, ¿©·¯ºÐÀº µµ´ÞºÒ´É Æ÷Æ®¸¦ Àбâ À§ÇØ ÇÊ¿äÇÑ raw ICMP ¼ÒÄÏÀ» »ý¼ºÇϱâ À§Çؼ­´Â root °¡ µÇ¾î¾ß ÇÑ´Ù. "-u"¿É¼ÇÀº root ±ÇÇÑ »ç¿ëÀڵ鿡°Ô ÀÌ ½ºÄ³´×À» Áö¿øÇϱâ À§ÇØ ¾²ÀδÙ. ¾î¶² »ç¶÷µéÀº UDP ½ºÄ³´×Àº ºÒ¿ÏÀüÇÏ°í ¾µ¸ð¾ø´Â °ÍÀ¸·Î Ä¡ºÎÇÑ´Ù. ³ª´Â ±×µé¿¡°Ô ÃÖ±ÙÀÇ ¼Ö¶ó¸®½º rpcbind º¸¾ÈÇêÁ¡À» »ó±â½ÃÅ°°í ½Í´Ù. Rpcbind´Â 32770¹øÀ» ³Ñ¾î°£ Æ÷Æ® ¾îµò°¡¿¡ ¾Ë·ÁÁöÁö ¾ÊÀº UDP Æ÷Æ®¸¦ ¼û±â°í ÀÖ´Ù. 111 ¹ø Æ÷Æ®´Â firewall·Î °¡·ÁÁ® Àֱ⠶§¹®¿¡ ¹®Á¦°¡ µÇÁö ¾Ê°ÚÁö¸¸, 30000¹øº¸´Ù ³ôÀº ¹øÈ£ÀÇ Æ÷Æ®¸¦ ¿­°í ÀÖ´Ù´Â °ÍÀ» ¿©·¯ºÐÀÌ ¾î¶»°Ô ¾Ë °ÍÀΰ¡? -- UDP ½ºÄ³³Ê°¡ ÀÖ´Ù¸é ¿©·¯ºÐµµ ¾Ë ¼ö ÀÖ´Ù. -UDP recvfrom() °ú write() ½ºÄ³´× : root ±ÇÇÑÀÇ user°¡ ¾Æ´Ï¸é Æ÷Æ®µµ´ÞºÒ´É ¿¡·¯¸¦ Á÷ Á¢ ÀÐÀ» ¼ö°¡ ¾ø´Âµ¥ ¹ÝÇÏ¿©, ¸®´ª½º¸¦ ±× ¿¡·¯µéÀÌ Á¢¼öµÇ¾úÀ» ¶§ °£Á¢ÀûÀ¸·Î »ç¿ëÀÚ¿¡°Ô ¾Ë·ÁÁÙ ¸¸Å­ ÈǸ¢ÇÏ´Ù. ¿¹¸¦ µé¸é, ´ÝÇôÁø Æ÷Æ®·Î µÎ ¹ø° write() ÄÝÀº ÀϹÝÀûÀ¸·Î ½ÇÆÐÇÒ °ÍÀÌ´Ù. netcat°ú PluviusÀÇ pscan.c ¿Í °°Àº ¸¹Àº ½ºÄ³³ÊµéÀº ±×·¸°Ô ÇÑ´Ù. ³ª´Â ¶ÇÇϳª, non-blocking UDP¼ÒÄÏ¿¡ recvfrom()ÄÝÀ» ÇϰԵǸé ICMP ¿¡·¯¸¦ ¹ÞÁö ¸øÇß´Ù¸é ÀϹÝÀûÀ¸·Î EAGAIN("Try Again:Àç½Ãµµ", ¿¡·¯¹øÈ£ 13¹ø)À» ÀÀ´äÇÑ´Ù. ±×·¸Áö ¾Ê°í, ICMP ¿¡·¯¸¦ ¹Þ¾Ò´Ù¸é ECONNREFUSED( "Á¢¼Ó°ÅºÎ", ¿¡·¯¹øÈ£ 111¹ø)·Î ÀÀ´äÇÑ´Ù. ÀÌ ±â¼úÀº ·çÆ®±ÇÇÑÀÌ ¾Æ´Ñ »ç¿ëÀڵ鿡°Ô -u ¿É¼ÇÀ» »ç¿ëÇßÀ» ¶§, ¿­·ÁÁø Æ÷Æ®µéÀ» ÆÇ´ÜÇÏ ±â À§ÇØ ¾²¿©Áø´Ù. ·çÆ®±ÇÇÑ »ç¿ëÀÚµé·Î -l ¿É¼ÇÀ» ¾²¸é °­Á¦·Î ÀÌ ¹æ½ÄÀ» »ç¿ëÇÒ ¼ö ÀÖÁö ¸¸, ¹Ùº¸°°Àº ÁþÀÌ´Ù. - ICMP echo ½ºÄ³´× : ÀÌ°ÍÀº ½ÇÁ¦·Î Æ÷Æ®½ºÄ³´×ÀÌ ¾Æ´Ï´Ù. ICMP°¡ Æ÷Æ®ÀÇ Æ¯Â¡À» °¡Áö°í ÀÖÁö ¾Ê±â ¶§¹®ÀÌ´Ù. ±×·¯³ª, ÀÌ°ÍÀº ³×Æ®¿öÅ©³»¿¡¼­ ¾î¶² ¼­¹öµéÀÌ ½ÇÁ¦ °¡µ¿ÁßÀÎÁö¸¦ ping Å×½ºÆ®¸¦ ÅëÇؼ­ ÆÇ´ÜÇϴµ¥ ¶§¶§·Î À¯¿ëÇÏ´Ù. -P ¿É¼ÇÀÌ À̸¦ À§Çؼ­ ¾²ÀδÙ. ¶ÇÇÑ, ¿©·¯ºÐÀº ¸Å¿ì Å« ³×Æ®¿öÅ©¸¦ °Ë»öÇÒ ¶§ PING_TIMEOUT #defineÀ» Á¶Á¤Çϱ⸦ ¿øÇÒÁöµµ ¸ð¸¥´Ù. NMAP´Â ÀÌ ÀÛ¾÷À» º¸´Ù ½±°Ô Çϱâ À§Çؼ­ host/bitmask Ç¥ÇöÀ» Áö¿øÇÑ´Ù. ¿¹¸¦ µé ¾î, "nmap -P cert.org/24 152.148.0.0/16"Àº CERT³×Æ®¿öÅ©ÀÇ CŬ·¡½º¿Í BŬ·¡½ºÀÇ ÁÖ¼Ò Áß¿¡¼­ 152.148.*.*·Î ³ªÅ¸³»¾îÁö´Â ¸ðµç ÁÖ¼Ò¸¦ °Ë»öÇÒ °ÍÀÌ´Ù. ÇÑ °³ÀÇ Á¶Á÷¾ÈÀÇ 6bit ¼­ºê³ÝÀ» °Ë»öÇϱâ À§ÇÑ "Host/26"ÀÇ Ç¥Çöµµ À¯¿ëÇÏ´Ù. [Ư¡] Features nmap À» ¸¸µé±â Àü¿¡ ÀÎÅͳݰú »ç¼³ ³×Æ®¿öÅ©(ÀÎÆ®¶ó³ÝÀ̶õ ¸»Àº ¾²°í ½ÍÁö ¾Ê´Ù.)¿¡¼­ ´Ù¸¥ ½ºÄ³³Ê¸¦ ã´Âµ¥ ¸¹Àº ½Ã°£À» ½è´Ù. ³ª´Â Áö±Ý ÀÌ¿ë °¡´ÉÇÑ ÃÖ°íÀÇ ½ºÄ³³Êµé, Julian AssangeÀÇincluding strobe, HobbitÀÇ netcat, Uriel MaimonÀÇ stcp, PluviusÀÇ pscan, Dave GoldsmithÀ§ ident-scan¿Í wietse Venema ÀÇ SATAN tcp/udp µî ²Ï ¸¹Àº ¼öÀÇ ½ºÄ³³ÊµéÀ» »ç¿ëÇØ º¸¾Ò´Ù. ±×°ÍµéÀº ¸ðµÎ ¿ì¼öÇÑ ½ºÄ³³ÊµéÀÌ´Ù. »ç½Ç, ³ª´Â °á±¹ ´Ù¸¥ °ÍµéÀÇ ÃÖ°íÀÇ ±â´ÉµéÀ» Áö¿øÇÏ ±â À§ÇØ ±×°ÍµéÀÇ ³»ºÎ±¸Á¶±îÁö ¿¬±¸Çß´Ù. ¸¶Ä§³», /usr/local/sbin µð·ºÅ丮¿¡ ÀÖ´Â ¸¹Àº ¼öÀÇ ´Ù¸¥ ½ºÄ³³ÊµéÀ» ÇÔ²² »ç¿ëÇÏ´Â °Íº¸´Ù ¿ÀÈ÷·Á ¿ÏÀüÈ÷ »õ·Î¿î ½ºÄ³³Ê¸¦ ¸¸µå´Â °Ô ³´°Ú´Ù°í »ý°¢Çß´Ù. ³»°¡ ¸ðµç Äڵ带 ¾²´Â µ¿¾È, nmap´Â ±× ÀÌÀüÀÇ ½ºÄ³³Ê·ÎºÎÅÍ ¸¹Àº ÁÁÀº ¾ÆÀ̵ð¾îµéÀ» ¾ò¾î¿Ô´Ù. °Å±â¿¡ Fragmentation Scanning°°Àº »õ·Î¿î ±â¼ú°ú ´Ù¸¥ ½ºÄ³³Ê¿¡ ÀÖ¾ú´Ù¸é ÁÁ¾ÒÀ» °ÉÇÏ´Â ±â´ÉµéÀ» µ¡ºÙ¿© °¬´Ù. ¿©±â¿¡ nmapÀÇ À¯¿ëÇÑ Æ¯Â¡ Áß ¸î°³¸¦ Àû¾îº¸¾Ò´Ù. -µ¿Àû Áö¿¬ ½Ã°£ °è»ê : ¾î¶² ½ºÄ³³ÊµéÀº ÆÐŶµéÀ» ¹ß¼ÛÇϴµ¥ µå´Â Áö¿¬½Ã°£À» »ç¿ëÀÚ°¡ ³Ö¾î Áà¾ß ÇÑ´Ù. ÀÌ·± Á¤º¸±îÁö ³Ö¾îÁÖ¾î¾ß Çϳª? È®½ÇÇÏ°Ô È£½ºÆ®µé¿¡ PingÀ» ÇÒ ¼ö ÀÖ´Ù. ±×·¸Áö¸¸, È£½ºÆ®°¡ ¸¹Àº ¼öÀÇ ¿äûÀ» ¹Þ¾ÒÀ» °æ¿ì¿£ ping°ªÀÌ Á¦¸Ú´ë·Î º¯ÇÑ´Ù. ½â ÁÁÀº °Ç ¾Æ´Ï´Ù. nmapÀº ÀûÀýÇÑ Áö¿¬½Ã°£À» °è»êÇÏ·Á ¾Ö¾´´Ù. ´Ù½Ã Àü´ÞµÇ¾î ¿À´Â ÆÐŶÀ» Á¶»çÇÏ´Â °Íµµ ±×Áß ÇϳªÀÌ´Ù. ±× °á°ú ½ºÄµ °úÁ¤µ¿¾È Áö¿¬½Ã°£À» ¼öÁ¤ÇÒ ¼ö ÀÖ´Ù. ·çÆ® ±ÇÇÑÀ» °¡Áø »ç¿ëÀÚ°¡, Ãʱâ Áö¿¬ ½Ã°£À» ¾Æ´Â Áß¿ä ¹æ¹ýÀº ³»ºÎÀÇ ¡°ÇΡ± ÇÔ¼ö È£Ã⠽ð£À» Àç´Â °ÍÀÌ´Ù. ·çÆ® ±ÇÇÑÀÌ ¾ø´Â »ç¿ëÀÚµéÀº , ¸ñÇ¥ È£½ºÆ®ÀÇ ´ÝÈù Æ÷Æ®¿¡ connect() ÇÔ¼ö¸¦ ½á¼­ À纻´Ù. À̹æ¹ýÀ¸·Î ±×·°Àú·° ¾µ¸¸ÇÑ °ªÀ» ¾òÀ» ¼ö ÀÖ´Ù. µ¡ ºÙ¿©¼­ ¸»Çϸé Ȥ½Ã¶óµµ Áö¿¬½Ã°£À» ÀÚ½ÅÀÌ Á¤ÇÏ°í ½Í´Ù¸é -w ¿É¼ÇÀ» »ç¿ëÇÏ¸é µÇÁö¸¸, ±×¸® ÃßõÇÏ°í ½ÍÁö ¾Ê´Ù. -ÀçÀü¼Û retransmission: ¾î¶² ½ºÄ³³ÊµéÀº ´ÜÁö ¸ðµç °Ë»ç ÆÐŶµéÀ» º¸³»°í£¬ÀÀ´äÀ» ¸ðÀº´Ù. ±×·¯³ª µÇµ¹¾Æ¿À´Â ÆÐŶÀÌ ¼Õ½ÇµÉ °æ¿ì¿£ À߸øµÈ °á°ú¸¦ ¾ò°Ô µÈ´Ù. ƯÈ÷ ÆÐŶÀÌ ¼Õ½ÇµÇ³Ä ¾È µÇ³Ä´Â Á¡Àº ¼öµ¿ÀûÀÎ ½ºÄµ ¹æ¹ýÀÎ UDP ½ºÄµ°ú FIN ½ºÄµ¿¡¼­ Áß¿äÇÏ´Ù. ±× ½ºÄµÀÌ Ã£´Â °ªÀÌ ¾î´À Æ÷Æ®°¡ º¸³½ ÆÐŶ¿¡ ÀÀ´äÀ» ¾È Çϴ°¡ ÇÏ´Â Á¤º¸À̱⠶§¹®ÀÌ´Ù. ´ëºÎºÐÀÇ °æ¿ì, ÀÀ´äÇÏÁö ¾Ê´Â Æ÷Æ®µéÀ» À§ÇØ È®ÀÎÂ÷ nmap´Â ¼³Á¤ÇÑ °ª¸¸Å­ ÆÐŶÀ» ´Ù½Ã º¸³»º»´Ù. -º´·Ä Æ÷Æ® ½ºÄ³´× : ¾î¶² ½ºÄ³³ÊµéÀº Àüü 65535°³ÀÇ Æ÷Æ®¸¦ °Ë»çÇϴµ¥ Çѹø¿¡ Çϳª¾¿ Â÷·Ê·Î ½ºÄµÀ» ÇÑ´Ù. ¸Å¿ì ºü¸¥ ·ÎÄà ³×Æ®¿öÅ© »ó¿¡¼­¶ó¸é Àß ÀÛµ¿µÈ´Ù. ÀÎÅͳݰú °°Àº Ä¿´Ù¶õ ³×Æ®¿öÅ©¿¡¼­´Â ÀÌ·± ¼Óµµ·Ð ÇÒ ¼ö°¡ ¾ø´Ù. nmap´Â ¸ðµç TCP¿Í UDP ¸ðµåµé¿¡¼­ Non-Bolocking I/O(¿ªÀÚ ÁÖ:µüÈ÷ ¹ø¿ªÇÒ ¸»ÀÌ »ý°¢ÀÌ ³ªÁö ¾Ê´Â´Ù. ¸ØÃã¾øÀÌ ÇÑ´Ù°í »ý°¢ÇÏÀÚ. ÀÚ¼¼ÇÑ °Ç acceptÇÔ¼ö¿Í °ü·ÃÀÌ ÀÖ´Ù.)¿Í º´·Ä ½ºÄµÀ» »ç¿ëÇÑ´Ù. µ¿½Ã¿¡ º´·Ä·Î ÀÛµ¿ÇÏ´Â ½ºÄµÀÇ ¼ö´Â -M(ÃÖ´ë ¼ÒÄÏ ¿É¼Ç)À¸·Î ¼³Á¤ÇÒ ¼ö ÀÖ´Ù. ¸Å¿ì ºü¸¥ ³×Æ®¿öÅ©¿¡¼­ ÀÌ °ªÀ» 18 ȤÀº ±× ÀÌ»óÀ¸·Î ´Ã¸°´Ù¸é ½ÇÇà¼Óµµ ÀúÇÏ°¡ ³ª¿ÀÁö¸¸, ´À¸° ³×Æ®¿öÅ©¿¡¼­´Â ¸¸Á·ÇÒ ¸¸ÇÑ ½ÇÇà¼Óµµ Çâ»óÀÌ ÀÖ´Ù. À¯¿¬ÇÑ Æ÷Æ® ÁöÁ¤ Flexible port specification : ³ª´Â Ç×»ó ¸ðµç 65535ÀÇ Æ÷Æ®µéÀ» ½ºÄµÇÏ°í ½ÍÁö´Â ¾Ê´Ù. ¶ÇÇÑ 1 ºÎÅÍ N °ª±îÁö ½ºÄµÇÒ ¼ö ÀÖ´Â ½ºÄ³³Êµµ ¸¶À½¿¡ µéÁö ¾Ê´Â´Ù. -p ¿É¼ÇÀ¸·Î ½ºÄµÀ» À§ÇØ Æ÷Æ®µé°ú ¹üÀ§µéÀ» ¸¶À½´ë·Î ÁöÁ¤ÇÒ ¼ö ÀÖ´Ù. ¿¹¸¦ µé¸é,¡®-p 21-25,80,113,60000-¡¯ ÀÌ·¸°Ô ÀûÀº ¶æÀº (³¡¿¡ µû¶ó¿À´Â ÇÏÀÌÇÂÀº 65535¶õ °ªÀÌ »ý·«µÇ¾î ÀÖ°í ¾Õ¼­ ³ª¿À´Â ÇÏÀÌÇÂÀº 1¿¡¼­ ºÎÅÍ ½ÃÀÛÇÏ´Â °É ÀǹÌÇÑ´Ù) 21ºÎÅÍ-25 Æ÷Æ® ±×¸®°í 80 ¶ÇÇÑ 113¹ø Æ÷Æ®¿Í 60000ºÎÅÍ 65535 ±îÁö Æ÷Æ®¸¦ °Ë»çÇ϶ó´Â ¸»ÀÌ´Ù. /etc/services¿¡¼­ ¼³Á¤µÈ Æ÷Æ®µé¸¸À» °Ë»çÇÏ´Â -F(ºü¸¥) ¿É¼ÇÀ» »ç¿ëÇÒ ¼ö ÀÖ´Ù. À¯¿¬ÇÑ ¸ñÇ¥ ÁöÁ¤ Flexible target specification : ³ª´Â ÇÑ°³ÀÇ È£½ºÆ®ÀÌ»óÀ» ÀÚÁÖ ½ºÄµÇÏ°í ½ÍÀºµ¥, ÀÏÀÏÈ÷ Ä¿´Ù¶õ ³×Æ®¿öÅ© »óÀÇ °¢°¢ÀÇ È£½ºÆ® ÁÖ¼Ò¸¦ ÀÏÀÏÀÌ Àû°í ½ÍÁö ¾Ê´Ù. nmapÀº nmapÀÇ ¿É¼Ç(¶Ç´Â ¿É¼Ç Àμö)ÀÌ ¾Æ´Ñ ¸ðµç °ÍÀº Ÿ°Ù È£½ºÆ®·Î °£ÁÖÇÑ´Ù. ¾Õ¿¡¼­µµ ¸»ÇßÁö¸¸, È£½ºÆ® À̸§À̳ª IP ÁÖ¼Ò¿¡ /mask¸¦ ¼±ÅÃÀûÀ¸·Î µ¡ºÙÀÌ¸é °°Àº °ªÀ» °°Àº ¸ðµç È£½ºÆ®µéÀ» °Ë»çÇÒ ¼ö ÀÖ´Ù. ´Ù¿î µÈ È£½ºÆ® °Ë»ç detection of down hosts : ¾î¶² ½ºÄ³³ÊµéÀº ´ë±Ô¸ð ³×Æ®¿öÅ©µµ °Ë»ç ÇÒ ¼ö ÀÖ´Ù. ±×·¯³ª ´Ù¿îµÈ È£½ºÆ®ÀÇ 65535°³ÀÇ Æ÷Æ®¸¦ °Ë»çÇÑ ´Ù´Â °Ç ½Ã°£ ³¶ºñ°¡ ¾Æ´Ò±î? nmapÀº ±âº»ÀûÀ¸·Î ´Ù¿îµÈ È£½ºÆ®ÀÎÁö ¾Æ´ÑÁö »çÀü¿¡ pingÀ» °¢°¢ÀÇ È£½ºÆ®¿¡ º¸³»¼­ ½Ã°£ ³¶ºñ¸¦ ¸·´Â´Ù. ÀÌ»óÇÑ Æ÷Æ®¿¡ °ªÀ» º¸³»¼­ ´Ù¿îµÈ È£½ºÆ®¸¦ ¾Æ´Âµ¥³ª À߸øÇؼ­ ³×Æ®¿öÅ© ÁÖ¼Ò³ª ºê·Îµå ij½ºÆ® ÁÖ¼Ò¸¦ º¸³ÂÀ» ¶§µµ À¯¿ëÇÏ´Ù.(¿ªÀÚ ÁÖ:¹«½¼ ¼Ò¸®ÀÎÁö Àß ¸ð¸£°Ú´Ù.) ¿ø¹®Àº It is also capable of bailing on hosts that seem down based on strange port scanning errors. It is also meant to be tolerant of people who accidentally scan network addresses, broadcast addresses , etc. ´ç½ÅÀÇ IP ÁÖ¼Ò °Ë»ç detection of your IP address: ¸î °¡Áö ÀÌÀ¯·Î ¸¹Àº ¼öÀÇ ½ºÄ³³Ê°¡ ÀԷ°ª Áß Çϳª·Î ´ç½ÅÀÇ IP ÁÖ¼Ò¸¦ ¿ä±¸ÇÑ´Ù. ifconfigÇϱ⵵ ½È°í ½ºÄµ ÇÒ ¶§¸¶´Ù ³» ÀÚ½ÅÀÇ ÁÖ¼Ò¸¦ ¾Æ´Â°É ¿øÄ¡ ¾Ê´Â´Ù. ¹°·Ð ÀԷ°ªÀ¸·Î ÁÖ´Â ¹æ¹ýÀÌ ÁÖ¼Ò°¡ ¹Ù²ð ¶§¸¶´Ù ´Ù½Ã ÄÄÆÄÀÏÇؼ­ »ç¿ëÇÏ´Â °Íº¸´Ù ÈξÀ ³´±ä ÇÏÁö¸¸. nmapÀÇ °æ¿ì´Â óÀ½¿¡ pingÀ» »ç¿ëÇÏ´Â µ¿¾È ÁÖ¼Ò¸¦ ¾Ë¾Æ³»°í, echo °ªÀ¸·Î µ¹¾Æ¿À´Â ÆÐŶÀÇ ¹Þ´Â ÁÖ¼Ò¸¦ »ç¿ëÇÑ´Ù. ±× °ªÀÌ router¸¦ Åë°úÇÏ´Â °ªÀÌ ±â ´ë¹®ÀÌ´Ù. ¸¸¾à ÀÌ·¸°Ô ¾È µÈ´Ù¸é(È£½ºÆ®¿¡ PingÀ» ÇÒ ¼ö°¡ ¾ø´Ù¸é) nmapd´Â °¢°¢ÀÇ ÀÎÅÍÆäÀ̽º¸¦ Á¶»çÇÏ°í ±× °ªÀ» »ç¿ëÇÑ´Ù. -S ¿É¼ÇÀ¸·Î ±×°ªÀ» ±×³É ÁöÁ¤ÇØ ÁÙ ¼ö ÀÖ´Ù. ±×·¯³ª ´Ù¸¥ »ç¶÷ÀÌ SYN°ú FIN ½ºÄµÀ» ÇÏ´Â °Íó·³ º¸À̱⸦ ¹Ù¶õ´Ù¸é ÀÌ ¿É¼ÇÀ» »ç¿ëÇÏÁö ¸¶¶ó. ´Ù¸¥ ¿É¼Çµé Some other, more minor options: -v (verbose): ´ëÈ­½ÄÀ¸·Î »ç¿ëÇÏ°í ½ÍÀ»¶§ ¾´¸é ÁÁ´Ù. ´Ù¸¥ À¯¿ëÇÑ ¸Þ½ÃÁöµµ ³ª¿À°í Á¤·ÄµÈ °á°ú°ªÀÌ ³ª¿À±â Àü¿¡ ¾î¶² Æ÷Æ®°¡ ¿­·È´ÂÁö ¸ÕÀú ¾Ë ¼ö ÀÖ´Ù.(¿ªÀÚ ÁÖ: ¼ºÁú ±ÞÇÑ »ç¶÷ ¿ëÀ̱º~) -r (randomize): ¸ñÇ¥ È£½ºÆ®ÀÇ Æ÷Æ®¸¦ ÀÓÀ¸·Î °Ë»çÇÑ´Ù.(¿ªÀÚ ÁÖ: ¿äÁò ³ª¿À´Â ÁÁÀº ħÀÔÀÚ °¨Áö ½Ã½ºÅÛÀº ÇÑ È£½ºÆ®¿¡¼­ Æ÷Æ® °Ë»ç°¡ Â÷·Ê·Î ¿À¸é ·Î±×¸¦ ³²±âµçÁö ¸·¾Æ¹ö¸°´Ù.) -q (quash argv): argv[0] °ªÀ» º¯È­½ÃÄѼ­ to FAKE_ARGV ("pine" ÀÌ ±âº»°ª)·Î º¸ÀÌ°Ô ÇÑ´Ù. ±×¸®°í ´Ù¸¥ ¿É¼ÇµéÀº Á¦°Å ½ÃÄÑ ¹ö¸°´Ù. w¿Í ps¸í·ÉÀ» Ä¥¶§ À§ÇèÇÏÁö ¾ÊÀº ÀÏÀ» ÇÏ´Â °Íó·³ º¸ÀδÙ. -h ¿É¼ÇÀ» ¿ä¾àÇؼ­ º¸¿©ÁØ´Ù. Also look for http://www.dhp.com/~fyodor/nmap/,±×¸®°í ±×°ÍÀº ³»°¡ ³ªÁß ¹öÀüµé°ú ´õ ¸¹Àº Á¤º¸¸¦ µÑ ¿¹Á¤ÀÇ À¥ »çÀÌÆ®ÀÌ´Ù. (¿ªÀÚ ÁÖ: ¾ðÁ¦ºÎÅÍ ÀÎ Áö´Â ¸ð¸£Áö¸¸ http://www.insecure.org/nmapÀ¸·Î ¹Ù²î¾ú´Ù.) [ÄÚµå] The code ¿ªÀÚ ÁÖ: Ȥ½Ã¶óµµ Äڵ忡 ÀÌÇØ°¡ Èûµé±îºÁ ¿ø¹®°ú ÇÔ²² ÆíÁýÇß½À´Ï´Ù. This should compile fine on any Linux box with 'gcc -O6 -o nmap nmap.c -lm'. It is distrubuted under the terms of the GNU GENERAL PUBLIC LICENSE. If you have problems or comments, feel free to mail me (fyodor@dhp.com). ÀÌ ÇÁ·Î±×·¥Àº 'gcc -O6 -o nmap nmap.c -lm'À̶ó°í ÇÏ¸é ¸®´ª½º¿¡¼­´Â Àß ÄÄÆÄÀÏ µÈ´Ù. ÀÌ ÇÁ·Î±×·¥Àº GNU GPL ¶óÀ̺귯¸® ÇÏ¿¡¼­ ¹èÆ÷µÈ´Ù. Ȥ½Ã ¹®Á¦°¡ »ý±â°Å³ª Áú¹®ÀÌ ÀÖ´Ù¸é fyodor@dhp.comÀ¸·Î ¿¬¶ôÁֱ⠹ٶõ´Ù. <++> nmap/Makefile # A trivial makefile for Network Mapper # ¾ÆÁÖ °£´ÜÇÑ nmapÀ» À§ÇÑ makefile nmap: nmap.c nmap.h gcc -Wall -O6 -o nmap nmap.c -lm <--> <++> nmap/nmap.h #ifndef NMAP_H #define NMAP_H /************************INCLUDES**********************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /**/ #include /**/ #include #include #include #include #include #include /************************DEFINES************************************/ /* #define to zero if you don't want to ignore hosts of the form xxx.xxx.xxx.{0,255} (usually network and broadcast addresses) */ /* ³×Æ®¿öÅ© ÀڽŰú ºê·Îµå ij½ºÆ® ÁÖ¼Ò¸¦ ¹«½ÃÇÏÁö ¾ÊÀ¸·Á¸é °ªÀ» 0À¸·Î Çϼ¼¿ä. */ #define IGNORE_ZERO_AND_255_HOSTS 1 #define DEBUGGING 0 /* Default number of ports in paralell. Doesn't always involve actual sockets. Can also adjust with the -M command line option. */ /* µ¿½Ã¿¡ ¿­¼ö ÀÖ´Â ¼ÒÄÏÀÇ °¹¼öÀÔ´Ï´Ù. ½ÇÁ¦ÀûÀ¸·Î Ç×»ó ¿­¼ö ÀÖ´Â ¼ÒÄÏ ¼ö´Â ¾Æ´Õ´Ï´Ù. -M ¿É¼ÇÀ¸·Î ¹Ù²Ü ÀÖ½À´Ï´Ù. */ #define MAX_SOCKETS 36 /* If reads of a UDP port keep returning EAGAIN (errno 13), do we want to count the port as valid? */ /* UDP Æ÷Æ®¿¡¼­ EAGAINÀ̶ó´Â ¿¡·¯ °ªÀ» ¾ò¾î³½´Ù¸é, ±× Æ÷Æ®´Â ¿­·Á ÀÖ´Â °É·Î °£ÁÖÇÒ±î¿ä? */ #define RISKY_UDP_SCAN 0 /* This ideally should be a port that isn't in use for any protocol on our machine or on the target */ /* ¾î¶² ¼­¹ö³ª ÀÌ Æ÷Æ®´Â »ç¿ëµÇÁö ¾Ê´Â´Ù°í ¿¹»óÇÒ ¼ö ÀÖ´Â Æ÷Æ® */ #define MAGIC_PORT 49724 /* How many udp sends without a ICMP port unreachable error does it take before we consider the port open? */ /* ¸î °³ÀÇ µµ´Þ ÇÒ ¼ö ¾ø´Ù´Â ICMP¸¦ ¿¡·¯¸¦ ¹Þ¾Æ¾ß ±× Æ÷Æ®°¡ ´ÝÇôÀÖ´Ù°í »ý°¢ÇÒ±î¿ä? */ #define UDP_MAX_PORT_RETRIES 4 /*How many seconds before we give up on a host being alive? */ /*¼­¹ö°¡ »ì¾ÆÀÖ´ÂÁö ÆÇ´ÜÇϱâÀ§ÇØ ±â´Ù¸®´Â ½Ã°£Àº? */ #define PING_TIMEOUT 2 #define FAKE_ARGV "pine" /* What ps and w should show if you use -q */ /* nmapÀÌ ps³ª w¿¡¼­´Â ¾î¶² ÇÁ·Î±×·¥À¸·Î º¸ÀÌ±æ ¿øÇϴ°¡¿ä? */ /* How do we want to log into ftp sites for */ /* ftp »çÀÌÆ®¿¡ µé¾î°¬À»¶§ log¿¡ ¾î¶»°Ô ³²±æ±î¿ä? */ #define FTPUSER "anonymous" #define FTPPASS "-wwwuser@" #define FTP_RETRIES 2 /* How many times should we relogin if we lose control connection? */ /* ¿¬°áÀÌ ²÷±æ °æ¿ì ¸î ¹ø Àç Á¢¼Ó ÇÒ±î¿ä? */ #define UC(b) (((int)b)&0xff) #define MORE_FRAGMENTS 8192 /*NOT a user serviceable parameter */ /* »ç¿ëÀÚ¿Í °ü·Ã ¾ø´Â Àμö */ #define fatal(x) { fprintf(stderr, "%s\n", x); exit(-1); } #define error(x) fprintf(stderr, "%s\n", x); /***********************STRUCTURES**********************************/ typedef struct port { unsigned short portno; unsigned char proto; char *owner; struct port *next; } port; struct ftpinfo { char user[64]; char pass[256]; /* methinks you're paranoid if you need this much space */ /* ´õ ¸¹Àº °ªÀÌ ÇÊ¿äÇÏ´Ù¸é ÆíÁýÁõÀÌ ½ÉÇϽñº¿ä. */ char server_name[MAXHOSTNAMELEN + 1]; struct in_addr server; unsigned short port; int sd; /* socket descriptor */ /* ¼ÒÄÏ º¯º°ÀÚ */ }; typedef port *portlist; /***********************PROTOTYPES**********************************/ /* print usage information */ /* »ç¿ëÀÚ Á¤º¸ Ãâ·Â */ void printusage(char *name); /* our scanning functions */ portlist tcp_scan(struct in_addr target, unsigned short *portarray, portlist *ports); portlist syn_scan(struct in_addr target, unsigned short *portarray, struct in_addr *source, int fragment, portlist *ports); portlist fin_scan(struct in_addr target, unsigned short *portarray, struct in_addr *source, int fragment, portlist *ports); portlist udp_scan(struct in_addr target, unsigned short *portarray, portlist *ports); portlist lamer_udp_scan(struct in_addr target, unsigned short *portarray, portlist *ports); portlist bounce_scan(struct in_addr target, unsigned short *portarray, struct ftpinfo *ftp, portlist *ports); /* Scan helper functions */ /* ½ºÄµÀ» µ½´Â ÇÔ¼ö */ unsigned long calculate_sleep(struct in_addr target); int check_ident_port(struct in_addr target); int getidentinfoz(struct in_addr target, int localport, int remoteport, char *owner); int parse_bounce(struct ftpinfo *ftp, char *url); int ftp_anon_connect(struct ftpinfo *ftp); /* port manipulators */ /* Æ÷Æ®¸¦ Á¶Á¤ÇÔ¼ö */ unsigned short *getpts(char *expr); /* someone stole the name getports()! */ unsigned short *getfastports(int tcpscan, int udpscan); int addport(portlist *ports, unsigned short portno, unsigned short protocol, char *owner); int deleteport(portlist *ports, unsigned short portno, unsigned short protocol); void printandfreeports(portlist ports); int shortfry(unsigned short *ports); /* socket manipulation functions */ /* ¼ÒÄÏ Á¶Á¤ ÇÔ¼ö */ void init_socket(int sd); int unblock_socket(int sd); int block_socket(int sd); int recvtime(int sd, char *buf, int len, int seconds); /* RAW packet building/dissasembling stuff */ /* Raw ÆÐŶÀ» ¸¸µé°í ºÐ¼®ÇÏ´Â ÇÔ¼ö */ int send_tcp_raw( int sd, struct in_addr *source, struct in_addr *victim, unsigned short sport, unsigned short dport, unsigned long seq, unsigned long ack, unsigned char flags, unsigned short window, char *data, unsigned short datalen); int isup(struct in_addr target); unsigned short in_cksum(unsigned short *ptr,int nbytes); int send_small_fragz(int sd, struct in_addr *source, struct in_addr *victim, int sport, int dport, int flags); int readtcppacket(char *packet, int readdata); int listen_icmp(int icmpsock, unsigned short outports[], unsigned short numtries[], int *num_out, struct in_addr target, portlist *ports); /* general helper functions */ /* ÀϹÝÀûÀ¸·Î ¾²ÀÌ´Â Æí¸®ÇÑ ÇÔ¼ö */ void hdump(unsigned char *packet, int len); void *safe_malloc(int size); #endif /* NMAP_H */ <--> <++> nmap/nmap.c #include "nmap.h" /* global options */ /* Àüü ¿É¼Ç */ short debugging = DEBUGGING; short verbose = 0; int number_of_ports = 0; /* How many ports do we scan per machine? */ /* ¼­¹ö´ç ¸î°³ÀÇ Æ÷Æ®¸¦ ½ºÄµ ÇÒ °Ì´Ï±î? */ int max_parallel_sockets = MAX_SOCKETS; extern char *optarg; extern int optind; short isr00t = 0; short identscan = 0; char current_name[MAXHOSTNAMELEN + 1]; unsigned long global_delay = 0; unsigned long global_rtt = 0; struct in_addr ouraddr = { 0 }; int main(int argc, char *argv[]) { int i, j, arg, argvlen; short fastscan=0, tcpscan=0, udpscan=0, synscan=0, randomize=0; short fragscan = 0, finscan = 0, quashargv = 0, pingscan = 0, lamerscan = 0; short bouncescan = 0; short *ports = NULL, mask; struct ftpinfo ftp = { FTPUSER, FTPPASS, "", { 0 }, 21, 0}; portlist openports = NULL; struct hostent *target = 0; unsigned long int lastip, currentip, longtmp; char *target_net, *p; struct in_addr current_in, *source=NULL; int hostup = 0; char *fakeargv[argc + 1]; /* argv faking silliness */ /* argv ¸¦ ¹Ù²Ù±â À§ÇÑ ºÎºÐ */ for(i=0; i < argc; i++) { fakeargv[i] = safe_malloc(strlen(argv[i]) + 1); strncpy(fakeargv[i], argv[i], strlen(argv[i]) + 1); } fakeargv[argc] = NULL; if (argc < 2 ) printusage(argv[0]); /* OK, lets parse these args! */ /* ÀÎÀÚµéÀ» °Ë»öÇÕ´Ï´Ù. */ while((arg = getopt(argc,fakeargv,"b:dFfhilM:Pp:qrS:stUuw:v")) != EOF) { switch(arg) { case 'b': bouncescan++; if (parse_bounce(&ftp, optarg) < 0 ) { fprintf(stderr, "Your argument to -b is fucked up. Use the normal url style: user:pass@server:port or just use server and use default anon login\n Use -h for help\n"); } break; case 'd': debugging++; break; case 'F': fastscan++; break; case 'f': fragscan++; break; case 'h': case '?': printusage(argv[0]); case 'i': identscan++; break; case 'l': lamerscan++; udpscan++; break; case 'M': max_parallel_sockets = atoi(optarg); break; case 'P': pingscan++; break; case 'p': if (ports) fatal("Only 1 -p option allowed, seperate multiple ranges with commas."); ports = getpts(optarg); break; case 'r': randomize++; break; case 's': synscan++; break; case 'S': if (source) fatal("You can only use the source option once!\n"); source = safe_malloc(sizeof(struct in_addr)); if (!inet_aton(optarg, source)) fatal("You must give the source address in dotted deciman, currently.\n"); break; case 't': tcpscan++; break; case 'U': finscan++; break; case 'u': udpscan++; break; case 'q': quashargv++; break; case 'w': global_delay = atoi(optarg); break; case 'v': verbose++; } } /* Take care of user wierdness */ /* Ȥ½Ã¶óµµ »ç¿ëÀÚÀÇ ½Ç¼ö°¡ ÀÖÀ»±îºÁ */ isr00t = !(geteuid()|geteuid()); if (tcpscan && synscan) fatal("The -t and -s options can't be used together.\ If you are trying to do TCP SYN scanning, just use -s.\ For normal connect() style scanning, use -t"); if ((synscan || finscan || fragscan || pingscan) && !isr00t) fatal("Options specified require r00t privileges. You don't have them!"); if (!tcpscan && !udpscan && !synscan && !finscan && !bouncescan && !pingscan) { tcpscan++; if (verbose) error("No scantype specified, assuming vanilla tcp connect()\ scan. Use -P if you really don't want to portscan."); if (fastscan && ports) fatal("You can use -F (fastscan) OR -p for explicit port specification.\ Not both!\n"); } /* If he wants to bounce of an ftp site, that site better damn well be reachable! */ /* ftp »çÀÌÆ®¸¦ bounce °ø°ÝÀ» ÇÏ·Á¸é ±× »çÀÌÆ®°¡ ÀÛµ¿ÇØ¾ß °ÚÁö¿ä! */ if (bouncescan) { if (!inet_aton(ftp.server_name, &ftp.server)) { if ((target = gethostbyname(ftp.server_name))) memcpy(&ftp.server, target->h_addr_list[0], 4); else { fprintf(stderr, "Failed to resolve ftp bounce proxy hostname/IP: %s\n", ftp.server_name); exit(1); } } else if (verbose) printf("Resolved ftp bounce attack proxy to %s (%s).\n", target->h_name, inet_ntoa(ftp.server)); } printf("\nStarting nmap V 1.21 by Fyodor (fyodor@dhp.com, www.dhp.com/~fyodor/nmap/\n"); if (!verbose) error("Hint: The -v option notifies you of open ports as they are found.\n"); if (fastscan) ports = getfastports(synscan|tcpscan|fragscan|finscan|bouncescan, udpscan|lamerscan); if (!ports) ports = getpts("1-1024"); /* more fakeargv junk, BTW malloc'ing extra space in argv[0] doesn't work */ /* fakeargv¸¦ ÀÌ¿ëÇؼ­ argvÀÇ ³»¿ëÀ» ¹Ù²ß´Ï´Ù. ±Ùµ¥ argv[0]°ú °°Àº Å©±â¿©¾ß °ÚÁö¿ä. */ if (quashargv) { argvlen = strlen(argv[0]); if (argvlen < strlen(FAKE_ARGV)) fatal("If you want me to fake your argv, you need to call the program with a longer name. Try the full pathname, or rename it fyodorssuperdedouperportscanner"); strncpy(argv[0], FAKE_ARGV, strlen(FAKE_ARGV)); for(i = strlen(FAKE_ARGV); i < argvlen; i++) argv[0][i] = '\0'; for(i=1; i < argc; i++) { argvlen = strlen(argv[i]); for(j=0; j <= argvlen; j++) argv[i][j] = '\0'; } } srand(time(NULL)); while(optind < argc) { /* Time to parse the allowed mask */ /* mask¸¦ °Ë»ö */ target = NULL; target_net = strtok(strdup(fakeargv[optind]), "/"); mask = (p = strtok(NULL,""))? atoi(p) : 32; if (debugging) printf("Target network is %s, scanmask is %d\n", target_net, mask); if (!inet_aton(target_net, ¤t_in)) { if ((target = gethostbyname(target_net))) memcpy(¤tip, target->h_addr_list[0], 4); else { fprintf(stderr, "Failed to resolve given hostname/IP: %s\n", target_net); } } else currentip = current_in.s_addr; longtmp = ntohl(currentip); currentip = longtmp & (unsigned long) (0 - pow(2,32 - mask)); lastip = longtmp | (unsigned long) (pow(2,32 - mask) - 1); while (currentip <= lastip) { openports = NULL; longtmp = htonl(currentip); target = gethostbyaddr((char *) &longtmp, 4, AF_INET); current_in.s_addr = longtmp; if (target) strncpy(current_name, target->h_name, MAXHOSTNAMELEN); else current_name[0] = '\0'; current_name[MAXHOSTNAMELEN + 1] = '\0'; if (randomize) shortfry(ports); #ifdef IGNORE_ZERO_AND_255_HOSTS if (IGNORE_ZERO_AND_255_HOSTS && (!(currentip % 256) || currentip % 256 == 255)) { printf("Skipping host %s because IGNORE_ZERO_AND_255_HOSTS is set in the source.\n", inet_ntoa(current_in)); hostup = 0; } else{ #endif if (isr00t) { if (!(hostup = isup(current_in))) { if (!pingscan) printf("Host %s (%s) appears to be down, skipping scan.\n", current_name, inet_ntoa(current_in)); else printf("Host %s (%s) appears to be down\n", current_name, inet_ntoa(current_in)); } else if (debugging || pingscan) printf("Host %s (%s) appears to be up ... good.\n", current_name, inet_ntoa(current_in)); } else hostup = 1; /* We don't really check because the lamer isn't root.*/ } /* Time for some actual scanning! */ /* ½ÇÁ¦ÀûÀÎ ½ºÄµÀ» ÇÏ´Â ºÎºÐ */ if (hostup) { if (tcpscan) tcp_scan(current_in, ports, &openports); if (synscan) syn_scan(current_in, ports, source, fragscan, &openports); if (finscan) fin_scan(current_in, ports, source, fragscan, &openports); if (bouncescan) { if (ftp.sd <= 0) ftp_anon_connect(&ftp); if (ftp.sd > 0) bounce_scan(current_in, ports, &ftp, &openports); } if (udpscan) { if (!isr00t || lamerscan) lamer_udp_scan(current_in, ports, &openports); else udp_scan(current_in, ports, &openports); } if (!openports && !pingscan) printf("No ports open for host %s (%s)\n", current_name, inet_ntoa(current_in)); if (openports) { printf("Open ports on %s (%s):\n", current_name, inet_ntoa(current_in)); printandfreeports(openports); } } currentip++; } optind++; } return 0; } __inline__ int unblock_socket(int sd) { int options; /*Unblock our socket to prevent recvfrom from blocking forever on certain target ports. */ options = O_NONBLOCK | fcntl(sd, F_GETFL); fcntl(sd, F_SETFL, options); return 1; } __inline__ int block_socket(int sd) { int options; options = (~O_NONBLOCK) & fcntl(sd, F_GETFL); fcntl(sd, F_SETFL, options); return 1; } /* Currently only sets SO_LINGER, I haven't seen any evidence that this helps. I'll do more testing before dumping it. */ /* SO_LINGER¶ó°í ¼³Á¤ÇØ ³õ¾ÒÁö¸¸ ½ÇÁ¦·Î ÀÌ°Ô Àß ÀÛµ¿Çϵµ·Ï µ½´ÂÁö È®ÀÎÇØ º¸Áö ¸øÇß´Ù. */ __inline__ void init_socket(int sd) { struct linger l; l.l_onoff = 1; l.l_linger = 0; if (setsockopt(sd, SOL_SOCKET, SO_LINGER, &l, sizeof(struct linger))) { fprintf(stderr, "Problem setting socket SO_LINGER, errno: %d\n", errno); perror("setsockopt"); } } /* Convert a string like "-100,200-1024,3000-4000,60000-" into an array of port numbers*/ /* ³Ñ¾î¿Â Æ÷Æ®¿¡ °üÇÑ ÀÎÀÚ°ªÀ» Æ÷Æ®¿Í °ü·ÃµÈ ¹è¿­·Î ¹Ù²Û´Ù. */ unsigned short *getpts(char *origexpr) { int exlen = strlen(origexpr); char *p,*q; unsigned short *tmp, *ports; int i=0, j=0,start,end; char *expr = strdup(origexpr); ports = safe_malloc(65536 * sizeof(short)); i++; i--; for(;j < exlen; j++) if (expr[j] != ' ') expr[i++] = expr[j]; expr[i] = '\0'; exlen = i + 1; i=0; while((p = strchr(expr,','))) { *p = '\0'; if (*expr == '-') {start = 1; end = atoi(expr+ 1);} else { start = end = atoi(expr); if ((q = strchr(expr,'-')) && *(q+1) ) end = atoi(q + 1); else if (q && !*(q+1)) end = 65535; } if (debugging) printf("The first port is %d, and the last one is %d\n", start, end); if (start < 1 || start > end) fatal("Your port specifications are illegal!"); for(j=start; j <= end; j++) ports[i++] = j; expr = p + 1; } if (*expr == '-') { start = 1; end = atoi(expr+ 1); } else { start = end = atoi(expr); if ((q = strchr(expr,'-')) && *(q+1) ) end = atoi(q+1); else if (q && !*(q+1)) end = 65535; } if (debugging) printf("The first port is %d, and the last one is %d\n", start, end); if (start < 1 || start > end) fatal("Your port specifications are illegal!"); for(j=start; j <= end; j++) ports[i++] = j; number_of_ports = i; ports[i++] = 0; tmp = realloc(ports, i * sizeof(short)); free(expr); return tmp; } unsigned short *getfastports(int tcpscan, int udpscan) { int portindex = 0, res, lastport = 0; unsigned int portno = 0; unsigned short *ports; char proto[10]; char line[81]; FILE *fp; ports = safe_malloc(65535 * sizeof(unsigned short)); proto[0] = '\0'; if (!(fp = fopen("/etc/services", "r"))) { printf("We can't open /etc/services for reading! Fix your system or don't use -f\n"); perror("fopen"); exit(1); } while(fgets(line, 80, fp)) { res = sscanf(line, "%*s %u/%s", &portno, proto); if (res == 2 && portno != 0 && portno != lastport) { lastport = portno; if (tcpscan && proto[0] == 't') ports[portindex++] = portno; else if (udpscan && proto[0] == 'u') ports[portindex++] = portno; } } number_of_ports = portindex; ports[portindex++] = 0; return realloc(ports, portindex * sizeof(unsigned short)); } void printusage(char *name) { printf("%s [options] [hostname[/mask] . . .] options (none are required, most can be combined): -t tcp connect() port scan -s tcp SYN stealth port scan (must be root) -u UDP port scan, will use MUCH better version if you are root -U Uriel Maimon (P49-15) style FIN stealth scan. -l Do the lamer UDP scan even if root. Less accurate. -P ping \"scan\". Find which hosts on specified network(s) are up. -b ftp \"bounce attack\" port scan -f use tiny fragmented packets for SYN or FIN scan. -i Get identd (rfc 1413) info on listening TCP processes. -p ports: ex: \'-p 23\' will only try port 23 of the host(s) \'-p 20-30,63000-\' scans 20-30 and 63000-65535 default: 1-1024 -F fast scan. Only scans ports in /etc/services, a la strobe(1). -r randomize target port scanning order. -h help, print this junk. Also see http://www.dhp.com/~fyodor/nmap/ -S If you want to specify the source address of SYN or FYN scan. -v Verbose. Its use is recommended. Use twice for greater effect. -w delay. n microsecond delay. Not recommended unless needed. -M maximum number of parallel sockets. Larger isn't always better. -q quash argv to something benign, currently set to \"%s\". Hostnames specified as internet hostname or IP address. Optional '/mask' specifies subnet. cert.org/24 or 192.88.209.5/24 scan CERT's Class C.\n", name, FAKE_ARGV); exit(1); } portlist tcp_scan(struct in_addr target, unsigned short *portarray, portlist *ports) { int starttime, current_out = 0, res , deadindex = 0, i=0, j=0, k=0, max=0; struct sockaddr_in sock, stranger, mysock; int sockaddr_in_len = sizeof(struct sockaddr_in); int sockets[max_parallel_sockets], deadstack[max_parallel_sockets]; unsigned short portno[max_parallel_sockets]; char owner[513], buf[65536]; int tryident = identscan, current_socket /*actually it is a socket INDEX*/; fd_set fds_read, fds_write; struct timeval nowait = {0,0}, longwait = {7,0}; signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE so our 'write 0 bytes' test doesn't crash our program!*/ /* ÇÁ·Î±×·¥ÀÌ SIGPIPE °°Àº ½ÅÈ£¸¦ ¹Þ°í ´Ù¿î µÇÁö ¾Êµµ·Ï ½ÅÈ£¸¦ ¹«½ÃÇϵµ·Ï ¼³Á¤ */ owner[0] = '\0'; starttime = time(NULL); bzero((char *)&sock,sizeof(struct sockaddr_in)); sock.sin_addr.s_addr = target.s_addr; if (verbose || debugging) printf("Initiating TCP connect() scan against %s (%s)\n", current_name, inet_ntoa(sock.sin_addr)); sock.sin_family=AF_INET; FD_ZERO(&fds_read); FD_ZERO(&fds_write); if (tryident) tryident = check_ident_port(target); /* Initially, all of our sockets are "dead" */ /* ±âº»ÀûÀ¸·Î ¼ÒĹÀÌ Á×¾îÀÖ´Ù°í ±âº»°ªÀ» ¼³Á¤ÇÑ´Ù. */ for(i = 0 ; i < max_parallel_sockets; i++) { deadstack[deadindex++] = i; portno[i] = 0; } deadindex--; /* deadindex always points to the most recently added dead socket index */ /* deadindex´Â Ç×»ó ÃÖ±Ù¿¡ socket index¿¡ Ãß°¡µÈ °÷À» °¡¸£Å²´Ù. */ while(portarray[j]) { longwait.tv_sec = 7; longwait.tv_usec = nowait.tv_sec = nowait.tv_usec = 0; for(i=current_out; i < max_parallel_sockets && portarray[j]; i++, j++) { current_socket = deadstack[deadindex--]; if ((sockets[current_socket] = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {perror("Socket troubles"); exit(1);} if (sockets[current_socket] > max) max = sockets[current_socket]; current_out++; unblock_socket(sockets[current_socket]); init_socket(sockets[current_socket]); portno[current_socket] = portarray[j]; sock.sin_port = htons(portarray[j]); if ((res = connect(sockets[current_socket],(struct sockaddr *)&sock,sizeof(struct sockaddr)))!=-1) printf("WTF???? I think we got a successful connection in non-blocking!!@#$\n"); else { switch(errno) { case EINPROGRESS: /* The one I always see */ /* ÀÚÁÖ º¼ ¼ö ÀÖ´Â ºÎºÐ */ case EAGAIN: block_socket(sockets[current_socket]); FD_SET(sockets[current_socket], &fds_write); FD_SET(sockets[current_socket], &fds_read); break; default: printf("Strange error from connect: (%d)", errno); perror(""); /*falling through intentionally*/ /* °íÀÇÀûÀ¸·Î ½ÇÆÐ */ case ECONNREFUSED: if (max == sockets[current_socket]) max--; deadstack[++deadindex] = current_socket; current_out--; portno[current_socket] = 0; close(sockets[current_socket]); break; } } } if (!portarray[j]) sleep(1); /*wait a second for any last packets*/ /* ´Ê°Ô ¿Ã¼ö ÀÖ´Â ÆÐŶÀ» À§ÇØ ±â´Ù¸°´Ù. */ while((res = select(max + 1, &fds_read, &fds_write, NULL, (current_out < max_parallel_sockets)? &nowait : &longwait)) > 0) { for(k=0; k < max_parallel_sockets; k++) if (portno[k]) { if (FD_ISSET(sockets[k], &fds_write) && FD_ISSET(sockets[k], &fds_read)) { /*printf("Socket at port %hi is selectable for r & w.", portno[k]);*/ res = recvfrom(sockets[k], buf, 65536, 0, (struct sockaddr *) & stranger, &sockaddr_in_len); if (res >= 0) { if (debugging || verbose) printf("Adding TCP port %hi due to successful read.\n", portno[k]); if (tryident) { if ( getsockname(sockets[k], (struct sockaddr *) &mysock, &sockaddr_in_len ) ) { perror("getsockname"); exit(1); } tryident = getidentinfoz(target, ntohs(mysock.sin_port), portno[k], owner); } addport(ports, portno[k], IPPROTO_TCP, owner); } if (max == sockets[k]) max--; FD_CLR(sockets[k], &fds_read); FD_CLR(sockets[k], &fds_write); deadstack[++deadindex] = k; current_out--; portno[k] = 0; close(sockets[k]); } else if(FD_ISSET(sockets[k], &fds_write)) { /*printf("Socket at port %hi is selectable for w only.VERIFYING\n", portno[k]);*/ res = send(sockets[k], buf, 0, 0); if (res < 0 ) { signal(SIGPIPE, SIG_IGN); if (debugging > 1) printf("Bad port %hi caught by 0-byte write!\n", portno[k]); } else { if (debugging || verbose) printf("Adding TCP port %hi due to successful 0-byte write!\n", portno[k]); if (tryident) { if ( getsockname(sockets[k], (struct sockaddr *) &mysock , &sockaddr_in_len ) ) { perror("getsockname"); exit(1); } tryident = getidentinfoz(target, ntohs(mysock.sin_port), portno[k], owner); } addport(ports, portno[k], IPPROTO_TCP, owner); } if (max == sockets[k]) max--; FD_CLR(sockets[k], &fds_write); deadstack[++deadindex] = k; current_out--; portno[k] = 0; close(sockets[k]); } else if ( FD_ISSET(sockets[k], &fds_read) ) { printf("Socket at port %hi is selectable for r only. This is very wierd.\n", portno[k]); if (max == sockets[k]) max--; FD_CLR(sockets[k], &fds_read); deadstack[++deadindex] = k; current_out--; portno[k] = 0; close(sockets[k]); } else { /*printf("Socket at port %hi not selecting, readding.\n",portno[k]);*/ FD_SET(sockets[k], &fds_write); FD_SET(sockets[k], &fds_read); } } } } if (debugging || verbose) printf("Scanned %d ports in %ld seconds with %d parallel sockets.\n", number_of_ports, time(NULL) - starttime, max_parallel_sockets); return *ports; } /* gawd, my next project will be in c++ so I don't have to deal with this crap ... simple linked list implementation */ /* ³» ´ÙÀ½ ÇÁ·ÎÁ§Æ®´Â ÀÌ ´Ü¼ø ¿¬°á¸®½ºÆ®¸¦ ´Ù·ç´Â c++Àε¥ ²À ´Ù·ê ÇÊ¿ä°¡ ÀÖÀ»±î? */ int addport(portlist *ports, unsigned short portno, unsigned short protocol, char *owner) { struct port *current, *tmp; int len; if (*ports) { current = *ports; /* ù¹ø° °æ¿ì list¾Õ¿¡ Áý¾î ³Ö±â */ /* case 1: we add to the front of the list */ if (portno <= current->portno) { if (current->portno == portno && current->proto == protocol) { if (debugging || verbose) printf("Duplicate port (%hi/%s)\n", portno , (protocol == IPPROTO_TCP)? "tcp": "udp"); return -1; } tmp = current; *ports = safe_malloc(sizeof(struct port)); (*ports)->next = tmp; current = *ports; current->portno = portno; current->proto = protocol; if (owner && *owner) { len = strlen(owner); current->owner = malloc(sizeof(char) * (len + 1)); strncpy(current->owner, owner, len + 1); } else current->owner = NULL; } else { /* case 2: we add somewhere in the middle or end of the list */ /* µÎ¹ø° °æ¿ì listÀÇ Áß°£°ú ³¡¿¡ °ªÀ» Áý¾î³ÖÀ» ¼ö ÀÖ´Ù. */ while( current->next && current->next->portno < portno) current = current->next; if (current->next && current->next->portno == portno && current->next->proto == protocol) { if (debugging || verbose) printf("Duplicate port (%hi/%s)\n", portno , (protocol == IPPROTO_TCP)? "tcp": "udp"); return -1; } tmp = current->next; current->next = safe_malloc(sizeof(struct port)); current->next->next = tmp; tmp = current->next; tmp->portno = portno; tmp->proto = protocol; if (owner && *owner) { len = strlen(owner); tmp->owner = malloc(sizeof(char) * (len + 1)); strncpy(tmp->owner, owner, len + 1); } else tmp->owner = NULL; } } else { /* Case 3, list is null */ /* ¼¼¹ø° °æ¿ì list°¡ ºñ¾î ÀÖÀ» ¶§ */ *ports = safe_malloc(sizeof(struct port)); tmp = *ports; tmp->portno = portno; tmp->proto = protocol; if (owner && *owner) { len = strlen(owner); tmp->owner = safe_malloc(sizeof(char) * (len + 1)); strncpy(tmp->owner, owner, len + 1); } else tmp->owner = NULL; tmp->next = NULL; } return 0; /*success */ /* ¼º°ø */ } int deleteport(portlist *ports, unsigned short portno, unsigned short protocol) { portlist current, tmp; if (!*ports) { if (debugging > 1) error("Tried to delete from empty port list!"); return -1; } /* Case 1, deletion from front of list*/ /* ù¹ø° °æ¿ì ¸®½ºÆ® ¾Õ¿¡¼­ »èÁ¦ */ if ((*ports)->portno == portno && (*ports)->proto == protocol) { tmp = (*ports)->next; if ((*ports)->owner) free((*ports)->owner); free(*ports); *ports = tmp; } else { current = *ports; for(;current->next && (current->next->portno != portno || current->next->proto != protocol); current = current->next); if (!current->next) return -1; tmp = current->next; current->next = tmp->next; if (tmp->owner) free(tmp->owner); free(tmp); } return 0; /* success */ /* ¼º°ø */ } void *safe_malloc(int size) { void *mymem; if (size < 0) fatal("Tried to malloc negative amount of memmory!!!"); if ((mymem = malloc(size)) == NULL) fatal("Malloc Failed! Probably out of space."); return mymem; } void printandfreeports(portlist ports) { char protocol[4]; struct servent *service; port *current = ports, *tmp; printf("Port Number Protocol Service"); printf("%s", (identscan)?" Owner\n":"\n"); while(current != NULL) { strcpy(protocol,(current->proto == IPPROTO_TCP)? "tcp": "udp"); service = getservbyport(htons(current->portno), protocol); printf("%-13d%-11s%-16s%s\n", current->portno, protocol, (service)? service->s_name: "unknown", (current->owner)? current->owner : ""); tmp = current; current = current->next; if (tmp->owner) free(tmp->owner); free(tmp); } printf("\n"); } /* This is the version of udp_scan that uses raw ICMP sockets and requires root priviliges.*/ /* À̹öÀüÀÇ udp_scanÀº raw ICMP ¼ÒÄÏÀ» ÀÌ¿ëÇϹǷΠroot ±ÇÇÑÀÌ ÇÊ¿äÇÕ´Ï´Ù. */ portlist udp_scan(struct in_addr target, unsigned short *portarray, portlist *ports) { int icmpsock, udpsock, tmp, done=0, retries, bytes = 0, res, num_out = 0; int i=0,j=0, k=0, icmperrlimittime, max_tries = UDP_MAX_PORT_RETRIES; unsigned short outports[max_parallel_sockets], numtries[max_parallel_sockets]; struct sockaddr_in her; char senddata[] = "blah\n"; unsigned long starttime, sleeptime; struct timeval shortwait = {1, 0 }; fd_set fds_read, fds_write; bzero(outports, max_parallel_sockets * sizeof(unsigned short)); bzero(numtries, max_parallel_sockets * sizeof(unsigned short)); /* Some systems (like linux) follow the advice of rfc1812 and limit * the rate at which they will respons with icmp error messages * (like port unreachable). icmperrlimittime is to compensate for that. */ /* ¾î¶² ½Ã½ºÅÛÀÇ °æ¿ì´Â RFC 1812ÀÇ ±Ç°í¸¦ µû¶ó¼­ ƯÁ¤ºñÀ²·Î icmp¸Þ½ÃÁö(¿¹·Î µµ´ÞÇÒ ¼ö ¾ø´Ù´Â ¸Þ½ÃÁö)¸¦ º¸³»°Ô µÇ¸é ¾à°£¾¿ ½Ã°£Áö¿¬ ½ÃÄÑ ´äÇØÁØ´Ù. */ icmperrlimittime = 60000; sleeptime = (global_delay)? global_delay : (global_rtt)? (1.2 * global_rtt) + 30000 : 1e5; if (global_delay) icmperrlimittime = global_delay; starttime = time(NULL); FD_ZERO(&fds_read); FD_ZERO(&fds_write); if (verbose || debugging) printf("Initiating UDP (raw ICMP version) scan against %s (%s) using wait delay of %li usecs.\n", current_name, inet_ntoa(target), sleeptime); if ((icmpsock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) perror("Opening ICMP RAW socket"); if ((udpsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) perror("Opening datagram socket"); unblock_socket(icmpsock); her.sin_addr = target; her.sin_family = AF_INET; while(!done) { tmp = num_out; for(i=0; (i < max_parallel_sockets && portarray[j]) || i < tmp; i++) { close(udpsock); if ((udpsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) perror("Opening datagram socket"); if ((i > tmp && portarray[j]) || numtries[i] > 1) { if (i > tmp) her.sin_port = htons(portarray[j++]); else her.sin_port = htons(outports[i]); FD_SET(udpsock, &fds_write); FD_SET(icmpsock, &fds_read); shortwait.tv_sec = 1; shortwait.tv_usec = 0; usleep(icmperrlimittime); res = select(udpsock + 1, NULL, &fds_write, NULL, &shortwait); if (FD_ISSET(udpsock, &fds_write)) bytes = sendto(udpsock, senddata, sizeof(senddata), 0, (struct sockaddr *) &her, sizeof(struct sockaddr_in)); else { printf("udpsock not set for writing port %d!", ntohs(her.sin_port)); return *ports; } if (bytes <= 0) { if (errno == ECONNREFUSED) { retries = 10; do { /* This is from when I was using the same socket and would * (rather often) get strange connection refused errors, it * shouldn't happen now that I create a new udp socket for each * port. At some point I will probably go back to 1 socket again. */ /* ÀÌ°ÍÀº °°Àº ¼ÒÄÏÀ» ÀÌ¿ëÇÒ¶§ ¿¡·¯¸¦ °ÅºÎÇÏ´Â ÀÌ»óÇÑ ¿¬°áÀ» ¾òÀ» ¶§ »ç¿ëÇÑ´Ù. °¢°¢ÀÇ Æ÷Æ®¿¡ »õ·Î¿î udp¼ÒÄÏÀ» »ç¿ëÇÏÁø ¾Ê´Â´Ù. ¾î¶² ½ÃÁ¡¿¡¼­ ´Ù½Ã óÀ½ ¼ÒÄÏÀ¸·Î µ¹¾Æ°£´Ù. */ printf("sendto said connection refused on port %d but trying again anyway.\n", ntohs(her.sin_port)); usleep(icmperrlimittime); bytes = sendto(udpsock, senddata, sizeof(senddata), 0, (struct sockaddr *) &her, sizeof(struct sockaddr_in)); printf("This time it returned %d\n", bytes); } while(bytes <= 0 && retries-- > 0); } if (bytes <= 0) { printf("sendto returned %d.", bytes); fflush(stdout); perror("sendto"); } } if (bytes > 0 && i > tmp) { num_out++; outports[i] = portarray[j-1]; } } } usleep(sleeptime); tmp = listen_icmp(icmpsock, outports, numtries, &num_out, target, ports); if (debugging) printf("listen_icmp caught %d bad ports.\n", tmp); done = !portarray[j]; for (i=0,k=0; i < max_parallel_sockets; i++) if (outports[i]) { if (++numtries[i] > max_tries - 1) { if (debugging || verbose) printf("Adding port %d for 0 unreachable port generations\n", outports[i]); addport(ports, outports[i], IPPROTO_UDP, NULL); num_out--; outports[i] = numtries[i] = 0; } else { done = 0; outports[k] = outports[i]; numtries[k] = numtries[i]; if (k != i) outports[i] = numtries[i] = 0; k++; } } if (num_out == max_parallel_sockets) { printf("Numout is max sockets, that is a problem!\n"); sleep(1); /* Give some time for responses to trickle back, and possibly to reset the hosts ICMP error limit */ /* ÀÏÁ¤½Ã°£ º¸³¾ ¼ö ÀÕ´Â ICMP ¿¡·¯¸¦ º¸³»´Â ÇѰ踦 ³Ñ°í °¢±â µû·Î ¿À´Â ´äÀ» ¹ÞÀ» ½Ã°£À» ¾òÀ¸·Á ½Ã°£À» ´õ ÁØ´Ù. */ } } if (debugging || verbose) printf("The UDP raw ICMP scanned %d ports in %ld seconds with %d parallel sockets.\n", number_of_ports, time(NULL) - starttime, max_parallel_sockets); close(icmpsock); close(udpsock); return *ports; } int listen_icmp(int icmpsock, unsigned short outports[], unsigned short numtries[], int *num_out, struct in_addr target, portlist *ports) { char response[1024]; struct sockaddr_in stranger; int sockaddr_in_size = sizeof(struct sockaddr_in); struct in_addr bs; struct iphdr *ip = (struct iphdr *) response; struct icmphdr *icmp = (struct icmphdr *) (response + sizeof(struct iphdr)); struct iphdr *ip2; unsigned short *data; int badport, numcaught=0, bytes, i, tmptry=0, found=0; while ((bytes = recvfrom(icmpsock, response, 1024, 0, (struct sockaddr *) &stranger, &sockaddr_in_size)) > 0) { numcaught++; bs.s_addr = ip->saddr; if (ip->saddr == target.s_addr && ip->protocol == IPPROTO_ICMP && icmp->type == 3 && icmp->code == 3) { ip2 = (struct iphdr *) (response + 4 * ip->ihl + sizeof(struct icmphdr)); data = (unsigned short *) ((char *)ip2 + 4 * ip2->ihl); badport = ntohs(data[1]); /*delete it from our outports array */ found = 0; for(i=0; i < max_parallel_sockets; i++) if (outports[i] == badport) { found = 1; tmptry = numtries[i]; outports[i] = numtries[i] = 0; (*num_out)--; break; } if (debugging && found && tmptry > 0) printf("Badport: %d on try number %d\n", badport, tmptry); if (!found) { if (debugging) printf("Badport %d came in late, deleting from portlist.\n", badport); if (deleteport(ports, badport, IPPROTO_UDP) < 0) if (debugging) printf("Port deletion failed.\n"); } } else { printf("Funked up packet!\n"); } } return numcaught; } /* This fucntion is nonsens. I wrote it all, really optimized etc. Then found out that many hosts limit the rate at which they send icmp errors :( I will probably totally rewrite it to be much simpler at some point. For now I won't worry about it since it isn't a very important functions (UDP is lame, plus there is already a much better function for people who are r00t */ /* ÀÌ ÇÔ¼ö´Â Á» ÀÌ»óÇÏ´Ù. ÃÖÀûÈ­ ½ÃÄ×´Ù. ±×ÈÄ¿¡ ¸¹Àº È£½ºÆ®°¡ icmp¿¡·¯¸¦ º¸³»´Â ºñÀ²À» Á¦ÇÑÇÏ´Â°É ¾Ë¾Ò´Ù. ³­ ¾î´À Á¡¿¡¼­ °£´ÜÇÏ°Ô ´Ù½Ã ½è´Ù. Áö±ÝÀº ÀÌ°Ô Áß¿äÇÑ ÇÔ¼ö¶ó°í »ý°¢ÀÌ ¾È µÇ¾î º°·Î ½Å°æÀÌ ¾È ¾²ÀδÙ. UDP ÀÚü°¡ ºÎÁ·ÇÑ ºÎºÐÀÌ À־ root±ÇÇÑÀ» °¡Áø »ç¶÷ÀÌ ´õ À¯¸®ÇÏ´Ù. */ portlist lamer_udp_scan(struct in_addr target, unsigned short *portarray, portlist *ports) { int sockaddr_in_size = sizeof(struct sockaddr_in),i=0,j=0,k=0, bytes; int sockets[max_parallel_sockets], trynum[max_parallel_sockets]; unsigned short portno[max_parallel_sockets]; int last_open = 0; char response[1024]; struct sockaddr_in her, stranger; char data[] = "\nhelp\nquit\n"; unsigned long sleeptime; unsigned int starttime; /* Initialize our target sockaddr_in */ /* ¸ñÇ¥¸¦ ÇâÇÑ ¼ÒÄÏ ¼³Á¤ */ bzero((char *) &her, sizeof(struct sockaddr_in)); her.sin_family = AF_INET; her.sin_addr = target; if (global_delay) sleeptime = global_delay; else sleeptime = calculate_sleep(target) + 60000; /*large to be on the safe side */ /* ¾ÈÀüÇϵµ·Ï µÇµµ·Ï Å©°Ô Àâ´Â´Ù. */ if (verbose || debugging) printf("Initiating UDP scan against %s (%s), sleeptime: %li\n", current_name, inet_ntoa(target), sleeptime); starttime = time(NULL); for(i = 0 ; i < max_parallel_sockets; i++) trynum[i] = portno[i] = 0; while(portarray[j]) { for(i=0; i < max_parallel_sockets && portarray[j]; i++, j++) { if (i >= last_open) { if ((sockets[i] = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {perror("datagram socket troubles"); exit(1);} block_socket(sockets[i]); portno[i] = portarray[j]; } her.sin_port = htons(portarray[j]); bytes = sendto(sockets[i], data, sizeof(data), 0, (struct sockaddr *) &her, sizeof(struct sockaddr_in)); usleep(5000); if (debugging > 1) printf("Sent %d bytes on socket %d to port %hi, try number %d.\n", bytes, sockets[i], portno[i], trynum[i]); if (bytes < 0 ) { printf("Sendto returned %d the FIRST TIME!@#$!, errno %d\n", bytes, errno); perror(""); trynum[i] = portno[i] = 0; close(sockets[i]); } } last_open = i; /* Might need to change this to 1e6 if you are having problems*/ /* ¹®Á¦°¡ ÀÖ´Ù¸é 100000 ¶ó°í ½áº¸¶ó. */ usleep(sleeptime + 5e5); for(i=0; i < last_open ; i++) { if (portno[i]) { unblock_socket(sockets[i]); if ((bytes = recvfrom(sockets[i], response, 1024, 0, (struct sockaddr *) &stranger, &sockaddr_in_size)) == -1) { if (debugging > 1) printf("2nd recvfrom on port %d returned %d with errno %d.\n", portno[i], bytes, errno); if (errno == EAGAIN /*11*/) { if (trynum[i] < 2) trynum[i]++; else { if (RISKY_UDP_SCAN) { printf("Adding port %d after 3 EAGAIN errors.\n", portno[i]); addport(ports, portno[i], IPPROTO_UDP, NULL); } else if (debugging) printf("Skipping possible false positive, port %d\n", portno[i]); trynum[i] = portno[i] = 0; close(sockets[i]); } } else if (errno == ECONNREFUSED /*111*/) { if (debugging > 1) printf("Closing socket for port %d, ECONNREFUSED received.\n", portno[i]); trynum[i] = portno[i] = 0; close(sockets[i]); } else { printf("Curious recvfrom error (%d) on port %hi: ", errno, portno[i]); perror(""); trynum[i] = portno[i] = 0; close(sockets[i]); } } else /*bytes is positive*/ /* °ªÀÌ ¾ç¼öÀ̸é */{ if (debugging || verbose) printf("Adding UDP port %d due to positive read!\n", portno[i]); addport(ports,portno[i], IPPROTO_UDP, NULL); trynum[i] = portno[i] = 0; close(sockets[i]); } } } /* Update last_open, we need to create new sockets.*/ /* last_open±îÁö »ç¿ëµÇ¾î »õ·Î¿î ¼ÒÄÏÀÌ ´õ ÇÊ¿äÇÏ´Ù. */ for(i=0, k=0; i < last_open; i++) if (portno[i]) { close(sockets[i]); sockets[k] = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); /* unblock_socket(sockets[k]);*/ portno[k] = portno[i]; trynum[k] = trynum[i]; k++; } last_open = k; for(i=k; i < max_parallel_sockets; i++) trynum[i] = sockets[i] = portno[i] = 0; } if (debugging) printf("UDP scanned %d ports in %ld seconds with %d parallel sockets\n", number_of_ports, time(NULL) - starttime, max_parallel_sockets); return *ports; } /* This attempts to calculate the round trip time (rtt) to a host by timing a connect() to a port which isn't listening. A better approach is to time a ping (since it is more likely to get through firewalls. This is now implemented in isup() for users who are root. */ /* connect()ÇÔ¼ö¸¦ ÀÌ¿ëÇؼ­ ´ÝÈù Æ÷Æ®¿¡ °¬´Ù°¡ µ¹¾Æ¿À´Â ½Ã°£À» °è»êÇÑ´Ù. ´õ ÁÁÀº ¹æ¹ýÀº pingÀ» ¾²¸é µÈ´Ù. ÀÌ pingÀº ¹æÈ­º®±îÁö °¥ ¼ö ÀÖ°í root±ÇÇÑÀ» °¡Áø »ç¿ëÀÚ°¡ isup()À̶ó´Â ÇÔ¼ö¸¦ »ç¿ëÇؼ­ ¾µ ¼ö ÀÖ´Ù. */ unsigned long calculate_sleep(struct in_addr target) { struct timeval begin, end; int sd; struct sockaddr_in sock; int res; if ((sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {perror("Socket troubles"); exit(1);} sock.sin_family = AF_INET; sock.sin_addr.s_addr = target.s_addr; sock.sin_port = htons(MAGIC_PORT); gettimeofday(&begin, NULL); if ((res = connect(sd, (struct sockaddr *) &sock, sizeof(struct sockaddr_in))) != -1) printf("You might want to change MAGIC_PORT in the include file, it seems to be listening on the target host!\n"); close(sd); gettimeofday(&end, NULL); if (end.tv_sec - begin.tv_sec > 5 ) /*uh-oh!*/ return 0; return (end.tv_sec - begin.tv_sec) * 1000000 + (end.tv_usec - begin.tv_usec); } /* Checks whether the identd port (113) is open on the target machine. No sense wasting time trying it for each good port if it is down! */ /* ¸ñÇ¥¿¡ identd Æ÷Æ®°¡ ÀÛµ¿µÈ´Ù¸é °Ë»çÇÑ´Ù. ¸¸¾à ´Ù¿î µÇ¾úÀ» °æ¿ì¿£ ½Ã°£³¶ºñÀÏ »ÓÀÌ´Ù. */ int check_ident_port(struct in_addr target) { int sd; struct sockaddr_in sock; int res; if ((sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {perror("Socket troubles"); exit(1);} sock.sin_family = AF_INET; sock.sin_addr.s_addr = target.s_addr; sock.sin_port = htons(113); /*should use getservbyname(3), yeah, yeah */ res = connect(sd, (struct sockaddr *) &sock, sizeof(struct sockaddr_in)); close(sd); if (res < 0 ) { if (debugging || verbose) printf("identd port not active\n"); return 0; } if (debugging || verbose) printf("identd port is active\n"); return 1; } int getidentinfoz(struct in_addr target, int localport, int remoteport, char *owner) { int sd; struct sockaddr_in sock; int res; char request[15]; char response[1024]; char *p,*q; char *os; owner[0] = '\0'; if ((sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {perror("Socket troubles"); exit(1);} sock.sin_family = AF_INET; sock.sin_addr.s_addr = target.s_addr; sock.sin_port = htons(113); usleep(50000); /* If we aren't careful, we really MIGHT take out inetd, some are very fragile */ /* Á¶½É½º·´Áö ¸øÇϸé inetd¸¦ ¾²Áö ¸»¾Æ¾ß ÇÑ´Ù. ¾î¶² °ÍÀº ½±°Ô ´Ù¿î µÈ´Ù. */ res = connect(sd, (struct sockaddr *) &sock, sizeof(struct sockaddr_in)); if (res < 0 ) { if (debugging || verbose) printf("identd port not active now for some reason ... hope we didn't break it!\n"); close(sd); return 0; } sprintf(request,"%hi,%hi\r\n", remoteport, localport); if (debugging > 1) printf("Connected to identd, sending request: %s", request); if (write(sd, request, strlen(request) + 1) == -1) { perror("identd write"); close(sd); return 0; } else if ((res = read(sd, response, 1024)) == -1) { perror("reading from identd"); close(sd); return 0; } else { close(sd); if (debugging > 1) printf("Read %d bytes from identd: %s\n", res, response); if ((p = strchr(response, ':'))) { p++; if ((q = strtok(p, " :"))) { if (!strcasecmp( q, "error")) { if (debugging || verbose) printf("ERROR returned from identd\n"); return 0; } if ((os = strtok(NULL, " :"))) { if ((p = strtok(NULL, " :"))) { if ((q = strchr(p, '\r'))) *q = '\0'; if ((q = strchr(p, '\n'))) *q = '\0'; strncpy(owner, p, 512); owner[512] = '\0'; } } } } } return 1; } /* A relatively fast (or at least short ;) ping function. Doesn't require a seperate checksum function */ /* »ó´ëÀûÀ¸·Î ºü¸¥ ping ÇÔ¼ö¸¦ ÀÌ¿ëÇؼ­ °¢°¢ÀÇ checksum ÇÔ¼ö¸¦ ÇÊ¿ä·Î ÇÏÁö ¾Ê´Â´Ù. */ int isup(struct in_addr target) { int res, retries = 3; struct sockaddr_in sock; /*type(8bit)=8, code(8)=0 (echo REQUEST), checksum(16)=34190, id(16)=31337 */ #ifdef __LITTLE_ENDIAN_BITFIELD unsigned char ping[64] = { 0x8, 0x0, 0x8e, 0x85, 0x69, 0x7A }; #else unsigned char ping[64] = { 0x8, 0x0, 0x85, 0x8e, 0x7A, 0x69 }; #endif int sd; struct timeval tv; struct timeval start, end; fd_set fd_read; struct { struct iphdr ip; unsigned char type; unsigned char code; unsigned short checksum; unsigned short identifier; char crap[16536]; } response; sd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); bzero((char *)&sock,sizeof(struct sockaddr_in)); sock.sin_family=AF_INET; sock.sin_addr = target; if (debugging > 1) printf(" Sending 3 64 byte raw pings to host.\n"); gettimeofday(&start, NULL); while(--retries) { if ((res = sendto(sd,(char *) ping,64,0,(struct sockaddr *)&sock, sizeof(struct sockaddr))) != 64) { fprintf(stderr, "sendto in isup returned %d! skipping host.\n", res); return 0; } FD_ZERO(&fd_read); FD_SET(sd, &fd_read); tv.tv_sec = 0; tv.tv_usec = 1e6 * (PING_TIMEOUT / 3.0); while(1) { if ((res = select(sd + 1, &fd_read, NULL, NULL, &tv)) != 1) break; else { read(sd,&response,sizeof(response)); if (response.ip.saddr == target.s_addr && !response.type && !response.code && response.identifier == 31337) { gettimeofday(&end, NULL); global_rtt = (end.tv_sec - start.tv_sec) * 1e6 + end.tv_usec - start.tv_usec; ouraddr.s_addr = response.ip.daddr; close(sd); return 1; } } } } close(sd); return 0; } portlist syn_scan(struct in_addr target, unsigned short *portarray, struct in_addr *source, int fragment, portlist *ports) { int i=0, j=0, received, bytes, starttime; struct sockaddr_in from; int fromsize = sizeof(struct sockaddr_in); int sockets[max_parallel_sockets]; struct timeval tv; char packet[65535]; struct iphdr *ip = (struct iphdr *) packet; struct tcphdr *tcp = (struct tcphdr *) (packet + sizeof(struct iphdr)); fd_set fd_read, fd_write; int res; struct hostent *myhostent; char myname[MAXHOSTNAMELEN + 1]; int source_malloc = 0; FD_ZERO(&fd_read); FD_ZERO(&fd_write); tv.tv_sec = 7; tv.tv_usec = 0; if ((received = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) < 0 ) perror("socket trobles in syn_scan"); unblock_socket(received); FD_SET(received, &fd_read); /* First we take what is given to us as source. If that isn't valid, we take what should have swiped from the echo reply in our ping function. If THAT doesn't work either, we try to determine our address with gethostname and gethostbyname. Whew! */ /* ¸ÕÀú ÀÎÀÚ°¡ ¹«¾ð°¡ È®ÀÎÇÏ°í, À߸øµÇ¾úÀ¸¸é ping ÇÔ¼öÀÇ echo reply¸¦ Çغ»´Ù. ÀÛµ¿µÇÁö ¾Ê´Â´Ù¸é gethostname°ú gethostbynameÀ» ½á¼­ ÁÖ¼Ò¸¦ ¾Ë¾Æ³½´Ù. */ if (!source) { if (ouraddr.s_addr) { source = &ouraddr; } else { source = safe_malloc(sizeof(struct in_addr)); source_malloc = 1; if (gethostname(myname, MAXHOSTNAMELEN) || !(myhostent = gethostbyname(myname))) fatal("Your system is fucked up.\n"); memcpy(source, myhostent->h_addr_list[0], sizeof(struct in_addr)); } if (debugging) printf("We skillfully deduced that your address is %s\n", inet_ntoa(*source)); } starttime = time(NULL); do { for(i=0; i < max_parallel_sockets && portarray[j]; i++) { if ((sockets[i] = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0 ) perror("socket trobles in syn_scan"); else { if (fragment) send_small_fragz(sockets[i], source, &target, MAGIC_PORT, portarray[j++], TH_SYN); else send_tcp_raw(sockets[i], source , &target, MAGIC_PORT, portarray[j++],0,0,TH_SYN,0,0,0); usleep(10000); } } if ((res = select(received + 1, &fd_read, NULL, NULL, &tv)) < 0) perror("select problems in syn_scan"); else if (res > 0) { while ((bytes = recvfrom(received, packet, 65535, 0, (struct sockaddr *)&from, &fromsize)) > 0 ) { if (ip->saddr == target.s_addr) { if (tcp->th_flags & TH_RST) { if (debugging > 1) printf("Nothing open on port %d\n", ntohs(tcp->th_sport)); } else /*if (tcp->th_flags & TH_SYN && tcp->th_flags & TH_ACK)*/ { if (debugging || verbose) { printf("Possible catch on port %d! Here it is:\n", ntohs(tcp->th_sport)); readtcppacket(packet,1); } addport(ports, ntohs(tcp->th_sport), IPPROTO_TCP, NULL); } } } } for(i=0; i < max_parallel_sockets && portarray[j]; i++) close(sockets[i]); } while (portarray[j]); if (debugging || verbose) printf("The TCP SYN scan took %ld seconds to scan %d ports.\n", time(NULL) - starttime, number_of_ports); if (source_malloc) free(source); /* Gotta save those 4 bytes! ;) */ close(received); return *ports; } int send_tcp_raw( int sd, struct in_addr *source, struct in_addr *victim, unsigned short sport, unsigned short dport, unsigned long seq, unsigned long ack, unsigned char flags, unsigned short window, char *data, unsigned short datalen) { struct pseudo_header { /*for computing TCP checksum, see TCP/IP Illustrated p. 145 */ /* TCP checksum °è»ê */ unsigned long s_addr; unsigned long d_addr; char zer0; unsigned char protocol; unsigned short length; }; char packet[sizeof(struct iphdr) + sizeof(struct tcphdr) + datalen]; /*With these placement we get data and some field alignment so we aren't wasting too much in computing the checksum */ /* ¿ì¸®°¡ ¾òÀ» ¼ö ÀÖ´Â Á¤º¸¿Í Çʵå Á¤·ÄÀº checksum¿¡¼­ °è»êÇϴµ¥ ³Ê¹« ½Ã°£À» ¼ÒºñÇÏÁö ¾Ê´Â´Ù. */ struct iphdr *ip = (struct iphdr *) packet; struct tcphdr *tcp = (struct tcphdr *) (packet + sizeof(struct iphdr)); struct pseudo_header *pseudo = (struct pseudo_header *) (packet + sizeof(struct iphdr) - sizeof(struct pseudo_header)); int res; struct sockaddr_in sock; char myname[MAXHOSTNAMELEN + 1]; struct hostent *myhostent; int source_malloced = 0; /* check that required fields are there and not too silly */ /* ÇÊ¿äÇÑ ºÎºÐ¸¸ °Ë»çÇÏ´Â °Ç ±¦Âú´Ù. */ if ( !victim || !sport || !dport || sd < 0) { fprintf(stderr, "send_tcp_raw: One or more of your parameters suck!\n"); return -1; } /* if they didn't give a source address, fill in our first address */ /* ¿ì¸® ÁÖ¼Ò°¡ ¾ø´Ù¸é ±× ºÎºÐÀ» ä¿î´Ù. */ if (!source) { source_malloced = 1; source = safe_malloc(sizeof(struct in_addr)); if (gethostname(myname, MAXHOSTNAMELEN) || !(myhostent = gethostbyname(myname))) fatal("Your system is fucked up.\n"); memcpy(source, myhostent->h_addr_list[0], sizeof(struct in_addr)); if (debugging > 1) printf("We skillfully deduced that your address is %s\n", inet_ntoa(*source)); } /*do we even have to fill out this damn thing? This is a raw packet, after all */ /* ÀÌ°É ÇؾßÇØ? raw ÆÐŶÀÌ´Ù. */ sock.sin_family = AF_INET; sock.sin_port = htons(dport); sock.sin_addr.s_addr = victim->s_addr; bzero(packet, sizeof(struct iphdr) + sizeof(struct tcphdr)); pseudo->s_addr = source->s_addr; pseudo->d_addr = victim->s_addr; pseudo->protocol = IPPROTO_TCP; pseudo->length = htons(sizeof(struct tcphdr) + datalen); tcp->th_sport = htons(sport); tcp->th_dport = htons(dport); if (seq) tcp->th_seq = htonl(seq); else tcp->th_seq = rand() + rand(); if (flags & TH_ACK && ack) tcp->th_ack = htonl(seq); else if (flags & TH_ACK) tcp->th_ack = rand() + rand(); tcp->th_off = 5 /*words*/; tcp->th_flags = flags; if (window) tcp->th_win = window; else tcp->th_win = htons(2048); /* Who cares */ /* ¹¹°¡ ¹®Á¦¾ß? */ tcp->th_sum = in_cksum((unsigned short *)pseudo, sizeof(struct tcphdr) + sizeof(struct pseudo_header) + datalen); /* Now for the ip header */ /* IP Çì´õ */ bzero(packet, sizeof(struct iphdr)); ip->version = 4; ip->ihl = 5; ip->tot_len = htons(sizeof(struct iphdr) + sizeof(struct tcphdr) + datalen); ip->id = rand(); ip->ttl = 255; ip->protocol = IPPROTO_TCP; ip->saddr = source->s_addr; ip->daddr = victim->s_addr; ip->check = in_cksum((unsigned short *)ip, sizeof(struct iphdr)); if (debugging > 1) { printf("Raw TCP packet creation completed! Here it is:\n"); readtcppacket(packet,ntohs(ip->tot_len)); } if (debugging > 1) printf("\nTrying sendto(%d , packet, %d, 0 , %s , %d)\n", sd, ntohs(ip->tot_len), inet_ntoa(*victim), sizeof(struct sockaddr_in)); if ((res = sendto(sd, packet, ntohs(ip->tot_len), 0, (struct sockaddr *)&sock, sizeof(struct sockaddr_in))) == -1) { perror("sendto in send_tcp_raw"); if (source_malloced) free(source); return -1; } if (debugging > 1) printf("successfully sent %d bytes of raw_tcp!\n", res); if (source_malloced) free(source); return res; } /* A simple program I wrote to help in debugging, shows the important fields of a TCP packet*/ /* °£´ÜÇÑ ÇÁ·Î±×·¥ µð¹ö±ëµµ¿òµµ µÇ°í TCP ÆÐŶÀÇ Áß¿äÇÑ Çʵ带 º¸¿©ÁØ´Ù. */ int readtcppacket(char *packet, int readdata) { struct iphdr *ip = (struct iphdr *) packet; struct tcphdr *tcp = (struct tcphdr *) (packet + sizeof(struct iphdr)); char *data = packet + sizeof(struct iphdr) + sizeof(struct tcphdr); int tot_len; struct in_addr bullshit, bullshit2; char sourcehost[16]; int i; if (!packet) { fprintf(stderr, "readtcppacket: packet is NULL!\n"); return -1; } bullshit.s_addr = ip->saddr; bullshit2.s_addr = ip->daddr; tot_len = ntohs(ip->tot_len); strncpy(sourcehost, inet_ntoa(bullshit), 16); i = 4 * (ntohs(ip->ihl) + ntohs(tcp->th_off)); if (ip->protocol == IPPROTO_TCP) if (ip->frag_off) printf("Packet is fragmented, offset field: %u", ip->frag_off); else { printf("TCP packet: %s:%d -> %s:%d (total: %d bytes)\n", sourcehost, ntohs(tcp->th_sport), inet_ntoa(bullshit2), ntohs(tcp->th_dport), tot_len); printf("Flags: "); if (!tcp->th_flags) printf("(none)"); if (tcp->th_flags & TH_RST) printf("RST "); if (tcp->th_flags & TH_SYN) printf("SYN "); if (tcp->th_flags & TH_ACK) printf("ACK "); if (tcp->th_flags & TH_PUSH) printf("PSH "); if (tcp->th_flags & TH_FIN) printf("FIN "); if (tcp->th_flags & TH_URG) printf("URG "); printf("\n"); printf("ttl: %hi ", ip->ttl); if (tcp->th_flags & (TH_SYN | TH_ACK)) printf("Seq: %lu\tAck: %lu\n", tcp->th_seq, tcp->th_ack); else if (tcp->th_flags & TH_SYN) printf("Seq: %lu\n", ntohl(tcp->th_seq)); else if (tcp->th_flags & TH_ACK) printf("Ack: %lu\n", ntohl(tcp->th_ack)); } if (readdata && i < tot_len) { printf("Data portion:\n"); while(i < tot_len) printf("%2X%c", data[i], (++i%16)? ' ' : '\n'); printf("\n"); } return 0; } /* We don't exactly need real crypto here (thank god!)\n"*/ /* ½ÇÁ¦ÀûÀÎ crypto ÇÔ¼ö°¡ ÇÊ¿äÄ¡ ¾Ê¾Ò´Ù. */ int shortfry(unsigned short *ports) { int num; unsigned short tmp; int i; for(i=0; i < number_of_ports; i++) { num = rand() % (number_of_ports); tmp = ports[i]; ports[i] = ports[num]; ports[num] = tmp; } return 1; } /* Much of this is swiped from my send_tcp_raw function above, which doesn't support fragmentation */ /* ¾ÕÀÇ send_tcp_raw ÇÔ¼ö¿£ fragmentation ºÎºÐÀÌ ¾ø´Ù. */ int send_small_fragz(int sd, struct in_addr *source, struct in_addr *victim, int sport, int dport, int flags) { struct pseudo_header { /*for computing TCP checksum, see TCP/IP Illustrated p. 145 */ /* TCP checksum °è»ê */ unsigned long s_addr; unsigned long d_addr; char zer0; unsigned char protocol; unsigned short length; }; /*In this placement we get data and some field alignment so we aren't wasting too much to compute the TCP checksum.*/ /* TCP checksumÀ» °è»êÇϴµ¥ ±×¸® ½Ã°£ÀÌ °É¸®Áö ¾Ê´Â´Ù. */ char packet[sizeof(struct iphdr) + sizeof(struct tcphdr) + 100]; struct iphdr *ip = (struct iphdr *) packet; struct tcphdr *tcp = (struct tcphdr *) (packet + sizeof(struct iphdr)); struct pseudo_header *pseudo = (struct pseudo_header *) (packet + sizeof(struct iphdr) - sizeof(struct pseudo_header)); char *frag2 = packet + sizeof(struct iphdr) + 16; struct iphdr *ip2 = (struct iphdr *) (frag2 - sizeof(struct iphdr)); int res; struct sockaddr_in sock; int id; /*Why do we have to fill out this damn thing? This is a raw packet, after all */ /* ÀÌ·± Èûµç ÀÏÀ» ²À Çؾߵɱî? raw ÆÐŶ ¸¸µé±â */ sock.sin_family = AF_INET; sock.sin_port = htons(dport); sock.sin_addr.s_addr = victim->s_addr; bzero(packet, sizeof(struct iphdr) + sizeof(struct tcphdr)); pseudo->s_addr = source->s_addr; pseudo->d_addr = victim->s_addr; pseudo->protocol = IPPROTO_TCP; pseudo->length = htons(sizeof(struct tcphdr)); tcp->th_sport = htons(sport); tcp->th_dport = htons(dport); tcp->th_seq = rand() + rand(); tcp->th_off = 5 /*words*/; tcp->th_flags = flags; tcp->th_win = htons(2048); /* Who cares */ tcp->th_sum = in_cksum((unsigned short *)pseudo, sizeof(struct tcphdr) + sizeof(struct pseudo_header)); /* Now for the ip header of frag1 */ /* frag1d¸¦ À§ÇÑ ip Çì´õ */ bzero(packet, sizeof(struct iphdr)); ip->version = 4; ip->ihl = 5; /*RFC 791 allows 8 octet frags, but I get "operation not permitted" (EPERM) when I try that. */ /*RFC 791 8°³ÀÇ ºÎºÐ±îÁö Çã¿ëÇÑ´Ù. ±×·¯³ª ³»°¡ ÀÌ°É ÇßÀ»¶§ Àß ÀÛµ¿ µÇÁö ¾Ê¾Ò´Ù. */ ip->tot_len = htons(sizeof(struct iphdr) + 16); id = ip->id = rand(); ip->frag_off = htons(MORE_FRAGMENTS); ip->ttl = 255; ip->protocol = IPPROTO_TCP; ip->saddr = source->s_addr; ip->daddr = victim->s_addr; ip->check = in_cksum((unsigned short *)ip, sizeof(struct iphdr)); if (debugging > 1) { printf("Raw TCP packet fragment #1 creation completed! Here it is:\n"); hdump(packet,20); } if (debugging > 1) printf("\nTrying sendto(%d , packet, %d, 0 , %s , %d)\n", sd, ntohs(ip->tot_len), inet_ntoa(*victim), sizeof(struct sockaddr_in)); if ((res = sendto(sd, packet, ntohs(ip->tot_len), 0, (struct sockaddr *)&sock, sizeof(struct sockaddr_in))) == -1) { perror("sendto in send_syn_fragz"); return -1; } if (debugging > 1) printf("successfully sent %d bytes of raw_tcp!\n", res); /* Create the second fragment */ /* µÎ¹ø° Á¶°¢ ¸¸µé±â */ bzero(ip2, sizeof(struct iphdr)); ip2->version = 4; ip2->ihl = 5; ip2->tot_len = htons(sizeof(struct iphdr) + 4); /* the rest of our TCP packet */ /* ³ª¸ÓÁö TCP ÆÐŶ */ ip2->id = id; ip2->frag_off = htons(2); ip2->ttl = 255; ip2->protocol = IPPROTO_TCP; ip2->saddr = source->s_addr; ip2->daddr = victim->s_addr; ip2->check = in_cksum((unsigned short *)ip2, sizeof(struct iphdr)); if (debugging > 1) { printf("Raw TCP packet fragment creation completed! Here it is:\n"); hdump(packet,20); } if (debugging > 1) printf("\nTrying sendto(%d , ip2, %d, 0 , %s , %d)\n", sd, ntohs(ip2->tot_len), inet_ntoa(*victim), sizeof(struct sockaddr_in)); if ((res = sendto(sd, ip2, ntohs(ip2->tot_len), 0, (struct sockaddr *)&sock, sizeof(struct sockaddr_in))) == -1) { perror("sendto in send_tcp_raw"); return -1; } return 1; } /* Hex dump */ /* Çí»ç ´ýÇÁ */ void hdump(unsigned char *packet, int len) { unsigned int i=0, j=0; printf("Here it is:\n"); for(i=0; i < len; i++){ j = (unsigned) (packet[i]); printf("%-2X ", j); if (!((i+1)%16)) printf("\n"); else if (!((i+1)%4)) printf(" "); } printf("\n"); } portlist fin_scan(struct in_addr target, unsigned short *portarray, struct in_addr *source, int fragment, portlist *ports) { int rawsd, tcpsd; int done = 0, badport, starttime, someleft, i, j=0, retries=2; int source_malloc = 0; int waiting_period = retries, sockaddr_in_size = sizeof(struct sockaddr_in); int bytes, dupesinarow = 0; unsigned long timeout; struct hostent *myhostent; char response[65535], myname[513]; struct iphdr *ip = (struct iphdr *) response; struct tcphdr *tcp; unsigned short portno[max_parallel_sockets], trynum[max_parallel_sockets]; struct sockaddr_in stranger; timeout = (global_delay)? global_delay : (global_rtt)? (1.2 * global_rtt) + 10000 : 1e5; bzero(&stranger, sockaddr_in_size); bzero(portno, max_parallel_sockets * sizeof(unsigned short)); bzero(trynum, max_parallel_sockets * sizeof(unsigned short)); starttime = time(NULL); if (debugging || verbose) printf("Initiating FIN stealth scan against %s (%s), sleep delay: %ld useconds\n", current_name, inet_ntoa(target), timeout); if (!source) { if (ouraddr.s_addr) { source = &ouraddr; } else { source = safe_malloc(sizeof(struct in_addr)); source_malloc = 1; if (gethostname(myname, MAXHOSTNAMELEN) || !(myhostent = gethostbyname(myname))) fatal("Your system is fucked up.\n"); memcpy(source, myhostent->h_addr_list[0], sizeof(struct in_addr)); } if (debugging || verbose) printf("We skillfully deduced that your address is %s\n", inet_ntoa(*source)); } if ((rawsd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0 ) perror("socket trobles in fin_scan"); if ((tcpsd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) < 0 ) perror("socket trobles in fin_scan"); unblock_socket(tcpsd); while(!done) { for(i=0; i < max_parallel_sockets; i++) { if (!portno[i] && portarray[j]) { portno[i] = portarray[j++]; } if (portno[i]) { if (fragment) send_small_fragz(rawsd, source, &target, MAGIC_PORT, portno[i], TH_FIN); else send_tcp_raw(rawsd, source , &target, MAGIC_PORT, portno[i], 0, 0, TH_FIN, 0, 0, 0); usleep(10000); /* *WE* normally do not need this, but the target lamer often does */ } } usleep(timeout); dupesinarow = 0; while ((bytes = recvfrom(tcpsd, response, 65535, 0, (struct sockaddr *) &stranger, &sockaddr_in_size)) > 0) if (ip->saddr == target.s_addr) { tcp = (struct tcphdr *) (response + 4 * ip->ihl); if (tcp->th_flags & TH_RST) { badport = ntohs(tcp->th_sport); if (debugging > 1) printf("Nothing open on port %d\n", badport); /* delete the port from active scanning */ for(i=0; i < max_parallel_sockets; i++) if (portno[i] == badport) { if (debugging && trynum[i] > 0) printf("Bad port %d caught on fin scan, try number %d\n", badport, trynum[i] + 1); trynum[i] = 0; portno[i] = 0; break; } if (i == max_parallel_sockets) { if (debugging) printf("Late packet or dupe, deleting port %d.\n", badport); dupesinarow++; if (ports) deleteport(ports, badport, IPPROTO_TCP); } } else if (debugging > 1) { printf("Strange packet from target%d! Here it is:\n", ntohs(tcp->th_sport)); if (bytes >= 40) readtcppacket(response,1); else hdump(response,bytes); } } /* adjust waiting time if neccessary */ /* ÇÊ¿äÇÏ¸é ±â´Ù¸®´Â ½Ã°£À» Á¶Á¤ÇÑ´Ù. */ if (dupesinarow > 6) { if (debugging || verbose) printf("Slowing down send frequency due to multiple late packets.\n"); if (timeout < 10 * ((global_delay)? global_delay: global_rtt + 20000)) timeout *= 1.5; else { printf("Too many late packets despite send frequency decreases, skipping scan.\n"); if (source_malloc) free(source); return *ports; } } /* Ok, collect good ports (those that we haven't received responses too after all our retries */ /* ¸ðµç ½ÃµµÈÄ¿¡µµ ¾î¶² ÀÀ´äµµ ¹ÞÀ» ¼ö ¾ø´Â Æ÷Æ®¸¦ ¸ðÀº´Ù. */ someleft = 0; for(i=0; i < max_parallel_sockets; i++) if (portno[i]) { if (++trynum[i] >= retries) { if (verbose || debugging) printf("Good port %d detected by fin_scan!\n", portno[i]); addport(ports, portno[i], IPPROTO_TCP, NULL); send_tcp_raw( rawsd, source, &target, MAGIC_PORT, portno[i], 0, 0, TH_FIN, 0, 0, 0); portno[i] = trynum[i] = 0; } else someleft = 1; } if (!portarray[j] && (!someleft || --waiting_period <= 0)) done++; } if (debugging || verbose) printf("The TCP stealth FIN scan took %ld seconds to scan %d ports.\n", time(NULL) - starttime, number_of_ports); if (source_malloc) free(source); close(tcpsd); close(rawsd); return *ports; } int ftp_anon_connect(struct ftpinfo *ftp) { int sd; struct sockaddr_in sock; int res; char recvbuf[2048]; char command[512]; if (verbose || debugging) printf("Attempting connection to ftp://%s:%s@%s:%i\n", ftp->user, ftp->pass, ftp->server_name, ftp->port); if ((sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { perror("Couldn't create ftp_anon_connect socket"); return 0; } sock.sin_family = AF_INET; sock.sin_addr.s_addr = ftp->server.s_addr; sock.sin_port = htons(ftp->port); res = connect(sd, (struct sockaddr *) &sock, sizeof(struct sockaddr_in)); if (res < 0 ) { printf("Your ftp bounce proxy server won't talk to us!\n"); exit(1); } if (verbose || debugging) printf("Connected:"); while ((res = recvtime(sd, recvbuf, 2048,7)) > 0) if (debugging || verbose) { recvbuf[res] = '\0'; printf("%s", recvbuf); } if (res < 0) { perror("recv problem from ftp bounce server"); exit(1); } snprintf(command, 511, "USER %s\r\n", ftp->user); send(sd, command, strlen(command), 0); res = recvtime(sd, recvbuf, 2048,12); if (res <= 0) { perror("recv problem from ftp bounce server"); exit(1); } recvbuf[res] = '\0'; if (debugging) printf("sent username, received: %s", recvbuf); if (recvbuf[0] == '5') { printf("Your ftp bounce server doesn't like the username \"%s\"\n", ftp->user); exit(1); } snprintf(command, 511, "PASS %s\r\n", ftp->pass); send(sd, command, strlen(command), 0); res = recvtime(sd, recvbuf, 2048,12); if (res < 0) { perror("recv problem from ftp bounce server\n"); exit(1); } if (!res) printf("Timeout from bounce server ..."); else { recvbuf[res] = '\0'; if (debugging) printf("sent password, received: %s", recvbuf); if (recvbuf[0] == '5') { fprintf(stderr, "Your ftp bounce server refused login combo (%s/%s)\n", ftp->user, ftp->pass); exit(1); } } while ((res = recvtime(sd, recvbuf, 2048,2)) > 0) if (debugging) { recvbuf[res] = '\0'; printf("%s", recvbuf); } if (res < 0) { perror("recv problem from ftp bounce server"); exit(1); } if (verbose) printf("Login credentials accepted by ftp server!\n"); ftp->sd = sd; return sd; } int recvtime(int sd, char *buf, int len, int seconds) { int res; struct timeval timeout = {seconds, 0}; fd_set readfd; FD_ZERO(&readfd); FD_SET(sd, &readfd); res = select(sd + 1, &readfd, NULL, NULL, &timeout); if (res > 0 ) { res = recv(sd, buf, len, 0); if (res >= 0) return res; perror("recv in recvtime"); return 0; } else if (!res) return 0; perror("select() in recvtime"); return -1; } portlist bounce_scan(struct in_addr target, unsigned short *portarray, struct ftpinfo *ftp, portlist *ports) { int starttime, res , sd = ftp->sd, i=0; char *t = (char *)⌖ int retriesleft = FTP_RETRIES; char recvbuf[2048]; char targetstr[20]; char command[512]; snprintf(targetstr, 20, "%d,%d,%d,%d,0,", UC(t[0]), UC(t[1]), UC(t[2]), UC(t[3])); starttime = time(NULL); if (verbose || debugging) printf("Initiating TCP ftp bounce scan against %s (%s)\n", current_name, inet_ntoa(target)); for(i=0; portarray[i]; i++) { snprintf(command, 512, "PORT %s%i\r\n", targetstr, portarray[i]); if (send(sd, command, strlen(command), 0) < 0 ) { perror("send in bounce_scan"); if (retriesleft) { if (verbose || debugging) printf("Our ftp proxy server hung up on us! retrying\n"); retriesleft--; close(sd); ftp->sd = ftp_anon_connect(ftp); if (ftp->sd < 0) return *ports; sd = ftp->sd; i--; } else { fprintf(stderr, "Our socket descriptor is dead and we are out of retries. Giving up.\n"); close(sd); ftp->sd = -1; return *ports; } } else { /* Our send is good */ /* Àß º¸³Â´Ù¸é */ res = recvtime(sd, recvbuf, 2048,15); if (res <= 0) perror("recv problem from ftp bounce server\n"); else { /* our recv is good */ /* Àß ¹Þ¾Ò´Ù¸é */ recvbuf[res] = '\0'; if (debugging) printf("result of port query on port %i: %s", portarray[i], recvbuf); if (recvbuf[0] == '5') { if (portarray[i] > 1023) { fprintf(stderr, "Your ftp bounce server sucks, it won't let us feed bogus ports!\n"); exit(1); } else { fprintf(stderr, "Your ftp bounce server doesn't allow priviliged ports, skipping them.\n"); while(portarray[i] && portarray[i] < 1024) i++; if (!portarray[i]) { fprintf(stderr, "And you didn't want to scan any unpriviliged ports. Giving up.\n"); /* close(sd); ftp->sd = -1; return *ports;*/ /* screw this gentle return crap! This is an emergency! */ /* ¹®Á¦°¡ ÀÖ±º. */ exit(1); } } } else /* Not an error message */ /* ¿¡·¯ ¸Þ½ÃÁö°¡ ¾øÀ» °æ¿ì */ if (send(sd, "LIST\r\n", 6, 0) > 0 ) { res = recvtime(sd, recvbuf, 2048,12); if (res <= 0) perror("recv problem from ftp bounce server\n"); else { recvbuf[res] = '\0'; if (debugging) printf("result of LIST: %s", recvbuf); if (!strncmp(recvbuf, "500", 3)) { /* fuck, we are not aligned properly */ /* ¾Ë¸Â°Ô Á¤·ÄÀÌ ¾È µÆ´Ù. */ if (verbose || debugging) printf("misalignment detected ... correcting.\n"); res = recvtime(sd, recvbuf, 2048,10); } if (recvbuf[0] == '1' || recvbuf[0] == '2') { if (verbose || debugging) printf("Port number %i appears good.\n", portarray[i]); addport(ports, portarray[i], IPPROTO_TCP, NULL); if (recvbuf[0] == '1') { res = recvtime(sd, recvbuf, 2048,5); recvbuf[res] = '\0'; if ((res > 0) && debugging) printf("nxt line: %s", recvbuf); } } } } } } } if (debugging || verbose) printf("Scanned %d ports in %ld seconds via the Bounce scan.\n", number_of_ports, time(NULL) - starttime); return *ports; } /* parse a URL stype ftp string of the form user:pass@server:portno */ /* »ç¿ëÀÚ¿¡ ÀÖ´Â ¹®Àå¿¡¼­ URLÀ» °Ë»ö */ int parse_bounce(struct ftpinfo *ftp, char *url) { char *p = url,*q, *s; if ((q = strrchr(url, '@'))) /*we have username and/or pass */ /* »ç¿ëÀÚ¸¦ ¹Þ°Å³ª ±×³É ³Ñ¾î°¡°Å³ª */ { *(q++) = '\0'; if ((s = strchr(q, ':'))) { /* has portno */ *(s++) = '\0'; strncpy(ftp->server_name, q, MAXHOSTNAMELEN); ftp->port = atoi(s); } else strncpy(ftp->server_name, q, MAXHOSTNAMELEN); if ((s = strchr(p, ':'))) { /* User AND pass given */ /* »ç¿ëÀÚ°¡ Æнº¿öµå¸¦ ÁöÁ¤ÇÒ¶§ */ *(s++) = '\0'; strncpy(ftp->user, p, 63); strncpy(ftp->pass, s, 255); } else { /* Username ONLY given */ /* »ç¿ëÀÚ ¸í¸¸ ÁÙ¶§ */ printf("Assuming %s is a username, and using the default password: %s\n", p, ftp->pass); strncpy(ftp->user, p, 63); } } else /* no username or password given */ /* »ç¿ëÀÚ¸í°ú Æнº¿öµå¸¦ ¾È ÁÙ¶§ */ if ((s = strchr(url, ':'))) { /* portno is given */ /* Æ÷Æ® ¹øÈ£¸¦ ÁÙ¶§ */ *(s++) = '\0'; strncpy(ftp->server_name, url, MAXHOSTNAMELEN); ftp->port = atoi(s); } else /* default case, no username, password, or portnumber */ /* ±âº» °æ¿ì »ç¿ëÀÚ ¸í , Æнº¿öµå , Æ÷Æ®¹øÈ£µµ ¾È ÁÖ¾úÀ» ¶§ */ strncpy(ftp->server_name, url, MAXHOSTNAMELEN); ftp->user[63] = ftp->pass[255] = ftp->server_name[MAXHOSTNAMELEN] = 0; return 1; } /* * I'll bet you've never seen this function before (yeah right)! * standard swiped checksum routine. */ /* ÀÌ·± ÇÔ¼ö¸¦ º»ÀûÀÌ ¾øÀ»°É¿ä! ±âº»ÀûÀÎ checksum ·çƾ */ unsigned short in_cksum(unsigned short *ptr,int nbytes) { register long sum; /* assumes long == 32 bits */ /* longÀº 32ºñÆ® */ u_short oddbyte; register u_short answer; /* assumes u_short == 16 bits */ /* assume u_short´Â 16ºñÆ® */ /* * Our algorithm is simple, using a 32-bit accumulator (sum), * we add sequential 16-bit words to it, and at the end, fold back * all the carry bits from the top 16 bits into the lower 16 bits. */ /* ¾Ë°í¸®ÁòÀº °£´ÜÇÕ´Ï´Ù. 32ºñÆ® °¡»ê±â¸¦ ÀÌ¿ëÇÏ°í ¼øÂ÷ÀûÀÎ 16ºñÆ® ¿öµå¸¦ ´õÇÕ´Ï´Ù. »óÀ§ ºñÆ®¿¡¼­ ÇÏÀ§ 16ºñÆ®·Î Á¢½À´Ï´Ù. */ sum = 0; while (nbytes > 1) { sum += *ptr++; nbytes -= 2; } /* mop up an odd byte, if necessary */ /* °¡´ÉÇϸé Ȧ¼ö¹ÙÀÌÆ®¸¦ ¾ø¾Ø´Ù. */ if (nbytes == 1) { oddbyte = 0; /* make sure top half is zero */ /* 0À¸·Î ¸¸µç´Ù. */ *((u_char *) &oddbyte) = *(u_char *)ptr; /* one byte only */ /* ÇÑ ¹ÙÀÌÆ®¸¸ */ sum += oddbyte; } /* * Add back carry outs from top 16 bits to low 16 bits. */ /* »óÀ§ 16ºñÆ®¿¡¼­ ÇÏÀ§ 16ºñÆ®·Î ´Ù½Ã ´õÇÑ´Ù. */ sum = (sum >> 16) + (sum & 0xffff); /* add high-16 to low-16 */ /* »óÀ§¸¦ ÇÏÀ§·Î */ sum += (sum >> 16); /* add carry */ /* ij¸®¸¦ ´õÇÑ´Ù. */ answer = ~sum; /* ones-complement, then truncate to 16 bits */ /* 16ºñÆ®·Î ¿¬°áÇÑ´Ù. */ return(answer); } <--> ¿ªÀÚ ¿Ð: ¹ø¿ªÇØ ³õ°í º¸´Ï ³Ê¹« ºÎÁ·ÇÑ ºÎºÐÀÌ ¸¹±º¿ä. Àß ÀÌÇØ°¡ ¾È µÇ½Ã´Â ºÐÀ̳ª ÀÌ°Ô À߸ø ¹ø¿ªÀÌ µÈ ºÎºÐÀÌ ÀÖ´Ù¸é ÁöÀûÇØ ÁÖ¼¼¿ä. ¹®¼­¿¡ Àû¾îµå¸®°Ú½À´Ï´Ù. À̹®¼­´Â ¿ª½Ã GNU/GPL·Î ¹èÆ÷°¡ µË´Ï´Ù. ´Ù¸¥ °÷¿¡ ¾²½Ç·Á¸é ¸ÞÀÏ Á» ¶ç¿ì°í ½á ÁÖ¼¼¿ä.