大洲的小偷程序非常让人眼馋,无奈本diao丝程序员,一无RMB,二无论坛币,只能望洋兴叹,所幸我有web程序开发的经验,对于这个小偷程序的基本原理能猜到不少,本着自力更生,服务大众的精神,我自己实现了一个简易版,在此开源给大家,希望能赚点论坛币,早日进入email版见见世面。
1 s+ z7 Y/ t2 A- ^0 ]
1 u, y4 g# U& p# E7 P8 ?8 Q一、原理# @- M9 X. l: E, A2 i; k- b7 O
1.用户访问流程:: g& }' i; u% K: ~
(1)用户访问我们的冒牌站(A.com)
+ g* h9 E/ Q& |. c(2)网站后台程序根据用户的query参数(包括get/post/cookie)构造原始网站B.com的url,用后台程序去访问该url,此时可以拿到原始网站的html和header输出。这里有一点需要注意的是原始网站输出的头也不可以忽略,里面的set-cookie信息也可以转发给用户的,这样就可以实现注册和登陆原网站啦。
. c; @8 @: v+ F3 V( W$ b1 O$ G5 ~(3)对原始网站的html输出和header输出按某些规则做替换,比如把某些广告去掉啦,把B.com的地址替换成A.com啦,其实这一步是最关键的,也是玩法最多最好玩的部分
* T8 T- c3 g; t7 ~; m# r& m(4)将替换后的html和header输出给用户。/ d$ L6 x$ p3 n+ l0 B
3 D; w) [3 A) S4 J8 F2.规则替换的几种玩法:
/ q& ~0 K5 @' F7 g(1)最简单的当然是字符串和正则表达式了,这就不多说了! L d4 ~- v5 |8 L) Z
(2)用html解析库对html的dom节点做操作,然后重新生成html,比如可以把页面中的text node翻译成另一种语言,或者做文章重写,这样比较容易逃过搜索引擎的法眼。
% {2 w: x8 f' p1 P3 B据我所知每种语言都由若干个html库,比如php的有DOM、phpQuery等,java的有htmlcleaner等
4 F5 j* h& l7 ]* l, D9 D(3)在原始html代码的后面加入一些javascript代码,用来隐藏一些页面元素,或加入一些广告代码等
3 V/ V! ~8 W* b3 V
8 h; t* T/ Z& G1 L/ I: d0 @3.关于速度和性能:
1 @2 p8 N; [; l+ M- n3 a7 B(1)提到性能第一个想到的当然是缓存啦,我觉得最适合加缓存的地方就是上文1.1.2中提到的生成原始网站url后,这里可以对原始url做md5编码,访问一次改url后就把它的内容和头存到硬盘上,这样就不用每次都去原网站拉取了。做缓存的另一个好处是不用担心被原网站屏蔽。/ x! A6 V; a3 H5 k; Q- q$ i
* E7 u8 s0 N: i
(2)对于css,图片,js等静态文件,其实不用每个文件都让php访问原网站拉取,可以直接返回个302,让浏览器直接去原网站拉取。
- C- a4 H7 n2 ^+ H/ T* n5 y& g4 E2 V; u7 d4 p) _3 z2 A/ y
0 b; f2 g' u1 }二、实现
& F5 z/ N9 u B) |' H6 H! Z1.程序语言:
" z. h, U1 |# \2 j3 _* U# U其实这个东西哪种语言都能搞定,也都不麻烦,我对php比较熟,就选了php。3 {+ I8 ]5 r' } G: ]! J
2.一些准备工作:1 o/ x. U* B1 X8 [1 S5 @) q* _
(1)修改apache的rewrite规则,因为我们的程序只有一个文件,我们必须把所有接收到的请求都重定向到这个文件,这里我假设重定向到index.php,在apache的<VirtualHost>中加入这几句,如果是虚拟主机的话就修改.htaccess吧,不过我没试过,所以不知道怎么写re它的write规则' H9 O: V) x0 t) v, d: r
RewriteEngine on" A% F/ u' R) o2 F
RewriteCond %{DOCUMENT_ROOT}%{SCRIPT_FILENAME} -s [OR]
5 R5 a3 i/ P4 @$ l% ARewriteCond %{DOCUMENT_ROOT}%{SCRIPT_FILENAME} -l [OR]
% F/ v9 R5 h8 I" I- `0 U RewriteCond %{DOCUMENT_ROOT}%{SCRIPT_FILENAME} -d3 F4 f( \% n: k- |* v/ S4 H
RewriteRule ^.*$ - [NC,L]! `/ ^/ X. p+ Z" A1 Y
RewriteRule ^.*$ /index.php [NC,L]) T, g$ D2 l) r2 Q1 {
, ~ s6 [6 V1 P& {) a, G! R9 w( _1 H0 z/ W(2)安装php的http模块' _& V+ S" P: b/ t( k1 `" Z
php发http请求的函数库找了好几个,发现http模块是用起来最简单的,不过需要你会linux操作哦,安装方法在这里http://php.net/manual/en/http.install.php
' _: w3 i- o! [- Ups:如果安装不上或没有vps,请把下面程序的http模块的函数换成phpcurl等http lib
% h0 P/ V: m; F% N0 A1 v" B7 D2 @, X0 e: @1 ~* ]
3.index.php的代码:
0 x5 P2 c4 S! U2 Y/ {# C% s4 Y) Q9 g9 b4 }
- G/ m, g0 f: j3 _0 H2 k- k$host = $_SERVER['HTTP_HOST'];
5 s' i# R' Y6 g& ?//这里把假站的域名替换成原始网站的,用于生成原始url
% U# ]3 Y0 Q& R$host = str_ireplace('fake.com', "true.com", $host);
( x; T4 M8 W8 a( F: A A6 u$toUrl = sprintf("http://%s%s", $host,$_SERVER['REQUEST_URI']);% o- J7 I5 G7 X3 y/ f6 y, L2 ?
, H$ W' \1 U& O" @4 w. l$script_name = $_SERVER['SCRIPT_NAME'];) x* x& @& P' G" p
$arr = explode(".", $script_name);: b- }0 }/ Y) |7 F0 }* X6 X
$endName = $arr[count($arr) - 1];
) c6 I7 c) a! w _6 l2 G8 V S3 f, D8 N( F! G: I1 w
4 p, k* {" L8 Q; B) C//这些后缀结尾的url直接返回302
( q8 A* {! ~9 p$STATIC_END_NAME = array('css','xml','rss','gif','jpg','jpeg','js','axd','atom',
( q f, y: o' l$ n% L: h 'mml','txt','jad','htc',
5 q+ A% C6 L; Y+ \; ?; b& v 'png','tif','tiff','wbmp','ico','jng','bmp','svg',
4 R$ n9 M- S) K q 'jar','war','ear','hqx','doc','pdf','ps','eps','ai',% o7 H# \2 z% m" b$ `
'rtf', 'xls', 'ppt', 'wmlc', 'xhtml', 'cco', 'jardiff',, d" T0 B& j" J8 s9 T8 i
'jnlp', 'run', 'pl', 'pm', 'prc', 'pdb', 'rar', 'rpm',
5 O K7 f' ~/ k4 [3 ^1 F 'sea', 'swf', 'sit', 'tcl', 'tk', 'der', 'der', 'crt',
+ v ^' x# v# \: J 'xpi', 'zip', 'bin', 'exe', 'dll' ,'deb', 'dmg', 'eot',
+ j# a: M D9 N 'iso', 'img', 'msi', 'msp', 'msm' ,'mid', 'midi', 'kar',& D8 T7 @4 a& g3 l( k
'mp3', 'ra', '3gpp', '3gp', 'mpeg', 'mpg', 'mov', 'flv',
* B0 P3 a- P Z$ g$ h 'mng', 'asx', 'asf', 'wmv', 'avi');+ l- I3 Y; W' V
6 B& S8 d" i! V* v5 _" gif(in_array($endName ,$STATIC_END_NAME)) y6 X: G }8 L4 f9 y
{ s8 V& c- a1 J- ?( f5 x5 [
$headerStr = sprintf("Location: %s", $toUrl);
/ r! N6 d1 v# i. W$ U) G header( $headerStr, true, 302);# x# C, S- k+ C! Y [& O* T
exit;
8 b1 n& L& P* N7 f+ f}
! u1 s6 j6 r# k0 q3 J
" w- ]: ?: N, r. r: A( |//一个简单的cache
4 i6 R7 G! r; }function GetFromCache( $url)
% q! b8 e) |' z' y{- T" d! J* O1 h) ~# C; `# W
$current_dir = dirname(__FILE__);6 N% W8 z5 }8 w# K) W
$cache_dir = $current_dir . "/cache/";
& Z: t1 P1 D$ b( K1 h if( !is_dir( $cache_dir)): D$ W, z, }. E" E1 Y
{: x3 ~( l1 u9 p8 k
, L) f H/ ?- H$ s
mkdir($cache_dir);
2 R+ f& G7 J7 u `- q }
9 m9 t& M! q7 o# t& j" v. A7 y- Z: S7 s7 n( n5 O$ q3 g
$cache_file = $cache_dir . md5($url);9 L R$ Q1 Q- i. r/ O
if(file_exists( $cache_file))( |6 L0 T; i; _$ ~' E
{" z( ] ~- r8 c, G; J
$html = file_get_contents( $cache_file);2 C9 Z8 b9 |7 m$ }7 U! B0 O* d2 q
if($html == false)5 p- O" B+ g8 y- m7 P R
{: Q! P) }/ j1 k4 `" K; A
$html = "";9 P! K! f0 L) l& X$ w5 |
}
( |2 k. N% l: O( x1 @( A }else
2 [- G+ h7 l/ R4 s- X) k& i8 M {; S+ K- Y) U9 K }+ ?4 n; ~
//访问原始网站
% ]" U/ P$ V, y6 E6 i* G! x $data = http_get($url ,array('redirect' => 5, 'timeout' => 10), $http_info );
0 [& r8 F+ Y- e4 E $message = http_parse_message($data);
' @& ]2 f/ D: n$ T6 `" g$ C* E
) p' M5 u- m! ^ $html = trim($message->body);# g C5 }5 A( u2 x) I
7 v% C5 q8 I& u, r$ j
file_put_contents( $cache_file, $html);3 B) w; ?/ B% u6 Z: e
}% ?+ p1 e2 g+ ]7 Z+ z5 S4 v' f! x
% j# h( [+ u6 D: U0 O$ t& p4 a! j
return $html;* i: _# \7 f$ G* C R% u+ W) t
}) Y7 D7 ~+ s& E; M+ T. `; [2 |
1 `' {) M. _2 `2 C+ @) i$html = GetFromCache( $toUrl );+ G' }; G" q! O" _% h' Z v0 O
1 ?4 g& R+ r. W* l) n1 b2 I7 ^' V$ ^; u& ]. U' p
$html = str_replace("circleid.com", "circleid.us", $html);
4 s" p! R1 X8 T$ ~+ o$ `/ L8 V7 [0 K' x: @1 R5 [( N
$html = preg_replace('/<meta name=.*>/', "", $html);
2 q* D& a* L) C/ H( v* a, \% {" `9 A6 N5 z% c
& k5 D& l" u$ R" v4 E, K//注释的这两句是用phpquery操作
. J9 G4 d' r# E; p" ^//$body = htmlqp($body)->find('#header')->remove()->html(); a( h& `$ d, o0 ~3 e4 b) z7 \ ~
//$html = htmlqp($html)->find('#header')->remove()->document->saveHTML();5 n; l! q: i. d9 @! Y$ Z
7 ^4 S+ G2 Q+ Q% v" E$script = <<<EOD
* D" d8 ^5 Q) u<script>
' L- I% f% B- A% F: C$(document).ready(function() {# P. e9 q/ L5 C5 v' V+ ^' Q
$("#footer").remove();
* f/ r5 c& {# Y. |5 e) ^- f: h6 m) D( o& C; `# k
});
# Z. N9 b: z- m0 D5 c! Z, C8 M7 U6 t9 C8 Q
</script>5 R/ ?% b) }5 L& e4 B
* _3 N) M S+ ]# ^2 A, A: _
EOD;. q- [4 `1 [$ H) C. n- T
% ~0 E/ N2 ~7 n: v: K. Vecho($html . $script);
) [# _0 V7 {) |0 @4 z( U5 C
! }& q% P4 g2 z" G
" l6 R2 P+ Z; J5 M, X" i$ M/ O# s* P三、最后( b6 E, o6 ]5 o8 z7 X: O/ ~- p( U
1.总之,这个程序还很简陋,没有处理post和cookie参数,也没有配置管理模块,距离大洲的程序差距有一个大洲那么大,仅适合稍微懂点程序又有点好奇心的新手玩玩7 F1 @. f& D8 ~% V5 U
2.最后当然是希望大家不令赐分啦,您的论坛币是我继续分享的动力,哈哈( T. b7 t. O8 t4 ~+ h
6 A* N. r3 w4 W: N( U" [ |