Как стать автором
Обновить

Автоматизированное отслеживание посылок на основе 17track.net

В связи с тем, что с недавнего времени сайты Почты России, а также China Post поставили на свои сайты отслеживания посылок каптчи, а в случае с China Post — каптча еще довольно-таки непростая, возникла необходимость в «обходе» данных препятствий для обеспечения адекватной работы моего маленького сайта по автоматизированному отслеживанию посылок.


Начну с того, что к сожалению я — абсолютный ноль в написании «взломщиков» каптч, но к счастью, мне на глаза попался сайт 17track.net, поддерживающий отслеживание посылок чуть ли не на всех почтовых сервисах мира.

Вооружившись дебаггером Chrome, выяснил, что трек-код отсылается в Ajax-запросе в некоем закодированном виде. Порывшись в JS-ах сайта, нашел участок кода, отвечающий за кодирование. К сожалению, он оказался обфусцированным (в принципе это было ожидаемое поведение).

Чтобы не заниматься деобфускацией шифровальщика, воспользуемся замечательным продуктом Node.js, подняв с его помощью небольшой TCP-сервер, который на входе будет получать исходный трек-код, а на выходе будет отсылать нам его уже в закодированном виде.
Привожу листинг самого «сервера» 17track.js:
eval(function (p, a, c, k, e, r) { e = function (c) { return (c < 62 ? '' : e(parseInt(c / 62))) + ((c = c % 62) > 35 ? String.fromCharCode(c + 29) : c.toString(36)) }; if ('0'.replace(0, e) == 0) { while (c--) r[e(c)] = k[c]; k = [function (e) { return r[e] || e } ]; e = function () { return '([mQ-Z]|[1-4]\\w)' }; c = 1 }; while (c--) if (k[c]) p = p.replace(new RegExp('\\b' + e(c) + '\\b', 'g'), k[c]); return p } ('X EE(){X b(N,z,D,A,p){U w=S T(1x,0,1f,1y,1z,1A,4,1f,Y,1x,1y,Y,1B,1z,14,4,1C,1D,1D,1E,1E,1F,1F,1B,1t,1G,1G,1t,0,1C,1A,14,1f,1y,4,1F,1x,14,14,Y,1z,1f,1E,1G,Y,4,1B,1A,1y,1t,1F,1B,1G,1C,1A,1x,1C,1D,1D,0,1t,1E,0,1z);U v=S T(-1H,-1I,1J,1K,17,32,-1L,-1M,-1N,-1H,-1O,-1P,-1I,17,32,-1L,1Q,1g,-1M,0,-1P,1J,1K,-1R,1g,-1N,0,1Q,1S,-1O,-1R,1S,0,1K,-1L,17,-1M,-1R,-1O,1J,-1R,-1I,32,-1H,1K,32,1J,-1P,1S,-1O,17,-1N,1g,-1M,-1N,1g,1Q,0,-1I,1S,-1P,-1L,-1H,1Q);U u=S T(1T,1U,0,1V,1W,0,1X,1W,1Y,1Z,1Z,1h,21,1Y,1u,1T,1i,8,1U,18,22,1u,1V,1X,23,22,1h,23,8,21,18,1i,1U,1i,1Y,1T,1h,1U,1W,0,18,1Y,21,1W,1Z,18,0,1V,23,1h,1i,21,8,1X,22,1Z,1u,23,1T,1u,1X,8,1V,22);U t=S T(25,29,29,2a,2b,2c,2d,2e,0,2f,2f,2g,2h,0,2i,2d,1,19,2j,25,2a,2j,2e,2k,2c,1,2k,2i,19,2b,2g,2h,2i,2d,2f,2g,2h,0,0,2f,2k,2i,2c,1,25,29,29,2a,2g,2h,1,19,2d,2e,2b,2c,2e,2k,2j,25,2a,2j,19,2b);U s=S T(1a,2l,2m,2n,1b,1a,2o,2m,2p,1b,2q,2p,2n,2r,2s,2o,Z,2t,2t,0,2u,2v,2v,2q,2r,2u,0,2w,2l,Z,2w,2s,1b,2n,1a,Z,2o,2m,2n,2p,2q,2o,2r,2l,2p,1a,Z,2r,2v,2s,2w,2v,2m,0,2t,2w,2s,2q,2u,1b,0,2t,2l,2u);U q=S T(2x,2y,2z,2A,2y,16,2A,2B,2C,2D,2B,2x,2E,2C,1j,2F,0,2E,2G,2z,2H,2G,16,2I,2I,0,2D,2J,2F,2H,2J,1j,2C,16,2I,2H,2A,2B,2F,2x,2B,2C,1j,2F,2x,2A,2H,2y,2D,2J,0,2I,16,2z,2y,2D,2z,2E,2G,0,2J,1j,2E,2G);U o=S T(1k,2K,2L,0,1c,2L,2M,2N,2O,1k,0,2P,2,1l,2K,2Q,2R,2M,2S,2R,2P,1v,2N,2S,1v,1c,2Q,2O,2T,2,1l,2T,1l,2T,1k,2L,2L,2K,2K,2,2S,1l,2R,1k,2N,2Q,2M,2N,2Q,2P,2O,1v,2T,0,2,2O,0,2M,1v,1c,2P,2R,1c,2S);U l=S T(2U,1d,10,2V,11,2U,64,11,2W,2X,2V,1n,2Y,2Z,1d,64,2X,33,34,35,1n,2W,36,2Y,35,0,0,36,33,34,2Z,10,2Z,10,2Y,1d,64,36,1d,2Z,34,64,33,2X,36,11,10,2U,0,2V,2W,33,2X,34,2U,0,2V,1n,1n,35,35,2W,11,2Y);U C=a(N);U F=0,K,I,M,P,k,h,n,O,E;U x,H,g,r;U B,G;U L=z.1o;U y=0;U J=C.1o==32?3:9;V(J==3){E=D?S T(0,32,2):S T(30,-2,-2)}1p{E=D?S T(0,32,2,62,30,-2,64,96,2):S T(94,62,-2,32,64,2,30,-2,-2)}z+="\\0\\0\\0\\0\\0\\0\\0\\0";39="";1q="";V(A==1){x=(p.R(F++)<<24)|(p.R(F++)<<16)|(p.R(F++)<<8)|p.R(F++);g=(p.R(F++)<<24)|(p.R(F++)<<16)|(p.R(F++)<<8)|p.R(F++);F=0}while(F<L){V(D){n=(z.R(F++)<<16)|z.R(F++);O=(z.R(F++)<<16)|z.R(F++)}1p{n=(z.R(F++)<<24)|(z.R(F++)<<16)|(z.R(F++)<<8)|z.R(F++);O=(z.R(F++)<<24)|(z.R(F++)<<16)|(z.R(F++)<<8)|z.R(F++)}V(A==1){V(D){n^=x;O^=g}1p{H=x;r=g;x=n;g=O}}M=((n>>>4)^O)&3a;O^=M;n^=(M<<4);M=((n>>>16)^O)&W;O^=M;n^=(M<<16);M=((O>>>2)^n)&3b;n^=M;O^=(M<<2);M=((O>>>8)^n)&3c;n^=M;O^=(M<<8);M=((n>>>1)^O)&37;O^=M;n^=(M<<1);n=((n<<1)|(n>>>31));O=((O<<1)|(O>>>31));1r(I=0;I<J;I+=3){B=E[I+1];G=E[I+2];1r(K=E[I];K!=B;K+=G){k=O^C[K];h=((O>>>4)|(O<<28))^C[K+1];M=n;n=O;O=M^(v[(k>>>24)&63]|t[(k>>>16)&63]|q[(k>>>8)&63]|l[k&63]|w[(h>>>24)&63]|u[(h>>>16)&63]|s[(h>>>8)&63]|o[h&63])}M=n;n=O;O=M}n=((n>>>1)|(n<<31));O=((O>>>1)|(O<<31));M=((n>>>1)^O)&37;O^=M;n^=(M<<1);M=((O>>>8)^n)&3c;n^=M;O^=(M<<8);M=((O>>>2)^n)&3b;n^=M;O^=(M<<2);M=((n>>>16)^O)&W;O^=M;n^=(M<<16);M=((n>>>4)^O)&3a;O^=M;n^=(M<<4);V(A==1){V(D){x=n;g=O}1p{n^=H;O^=r}}V(D){1q+=3d.3e((n>>>24),((n>>>16)&1s),((n>>>8)&1s),(n&1s),(O>>>24),((O>>>16)&1s),((O>>>8)&1s),(O&1s))}1p{1q+=3d.3e(((n>>>16)&W),(n&W),((O>>>16)&W),(O&W))}D?y+=16:y+=8;V(y==18){39+=1q;1q="";y=0}}1e 39+1q}X a(r){3n=S T(0,4,1j,536870916,1f,1t,3o,536936452,18,516,536871424,536871428,66048,66052,536936960,536936964);3p=S T(0,1,17,1048577,1l,67108865,68157440,68157441,1a,3f,1048832,1048833,67109120,67109121,68157696,68157697);3q=S T(0,8,1c,3r,14,3s,3t,3u,0,8,1c,3r,14,3s,3t,3u);3v=S T(0,1k,1i,136314880,19,2105344,134225920,136323072,1h,2228224,1u,136445952,139264,2236416,134356992,136454144);3w=S T(0,10,16,3x,0,10,16,3x,1d,1n,3g,3y,1d,1n,3g,3y);3z=S T(0,Y,32,3A,0,Y,32,3A,Z,3B,3C,3D,Z,3B,3C,3D);3E=S T(0,11,1b,3F,2,3G,3H,3I,0,11,1b,3F,2,3G,3H,3I);3J=S T(0,1f,1c,67584,1j,3o,536872960,536938496,1h,196608,133120,198656,537001984,537067520,537004032,537069568);3K=S T(0,10,0,10,2,3L,2,3L,Z,3M,Z,3M,3N,3O,3N,3O);3P=S T(0,11,8,3Q,0,11,8,3Q,Y,3R,3S,3T,Y,3R,3S,3T);3U=S T(0,32,0,32,17,1g,17,1g,19,3V,19,3V,3W,3X,3W,3X);3Y=S T(0,14,18,16777728,1k,18874368,2097664,18874880,1l,83886080,67109376,83886592,1v,85983232,69206528,85983744);3Z=S T(0,1d,1i,134221824,1b,528384,134742016,134746112,16,3g,134217744,134221840,524304,528400,134742032,134746128);40=S T(0,4,1a,41,0,4,1a,41,1,5,3f,42,1,5,3f,42);U k=r.1o>=24?3:1;U t=S T(32*k);U q=S T(0,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0);U p,g,l=0,h=0,s;1r(U o=0;o<k;o++){Q=(r.R(l++)<<24)|(r.R(l++)<<16)|(r.R(l++)<<8)|r.R(l++);m=(r.R(l++)<<24)|(r.R(l++)<<16)|(r.R(l++)<<8)|r.R(l++);s=((Q>>>4)^m)&3a;m^=s;Q^=(s<<4);s=((m>>>-16)^Q)&W;Q^=s;m^=(s<<-16);s=((Q>>>2)^m)&3b;m^=s;Q^=(s<<2);s=((m>>>-16)^Q)&W;Q^=s;m^=(s<<-16);s=((Q>>>1)^m)&37;m^=s;Q^=(s<<1);s=((m>>>8)^Q)&3c;Q^=s;m^=(s<<8);s=((Q>>>1)^m)&37;m^=s;Q^=(s<<1);s=(Q<<8)|((m>>>20)&43);Q=(m<<24)|((m<<8)&16711680)|((m>>>8)&65280)|((m>>>24)&43);m=s;1r(i=0;i<q.1o;i++){V(q[i]){Q=(Q<<2)|(Q>>>26);m=(m<<2)|(m>>>26)}1p{Q=(Q<<1)|(Q>>>27);m=(m<<1)|(m>>>27)}Q&=-15;m&=-15;p=3n[Q>>>28]|3p[(Q>>>24)&15]|3q[(Q>>>20)&15]|3v[(Q>>>16)&15]|3w[(Q>>>12)&15]|3z[(Q>>>8)&15]|3E[(Q>>>4)&15];g=3J[m>>>28]|3K[(m>>>24)&15]|3P[(m>>>20)&15]|3U[(m>>>16)&15]|3Y[(m>>>12)&15]|3Z[(m>>>8)&15]|40[(m>>>4)&15];s=((g>>>16)^p)&W;t[h++]=p^s;t[h++]=g^(s<<16)}}1e t}X d(j){U k="";U h=S T("0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f");1r(U g=0;g<(j.1o);g++){k+=h[j.R(g)>>4]+h[j.R(g)&15]}1e k}X f(j){U k="";1r(U h=0;h<j.1o;h+=2){U g=parseInt(j.substring(h,h+2),16);k+=3d.3e(g)}1e k}X e(h,g){1e d(b(g,h,1,0))}X c(h,g){1e b(g,f(h),0,0)}this.dE=X(g){g+=",http://www.17track.net/ResultEn.html?refDate" + new Date().getTime();1e e(g,"\\1w\\x36\\44\\3h\\45\\3i\\1w\\3j\\38\\x33\\46\\3i\\x35\\38\\3k\\3l\\3k\\3k\\38\\45\\1w\\1w\\x42\\38\\47\\1w\\3i\\3h\\46\\3j\\47\\3l\\3h\\44\\3l\\3j")}};', [], 256, '||||||||||||||||||||||right||||||||||||||||||||||||||||||left|charCodeAt|new|Array|var|if|65535|function|1024|33554432|262144|268435456|||16777216|||1048576|512|8192|256|524288|2048|4096|return|65536|1048608|131072|134217728|536870912|2097152|67108864||266240|length|else|tempresult|for|255|65540|134348800|69206016|x45|16843776|16843780|16842756|66564|16778244|1028|16778240|66560|16842752|16777220|2146402272|2147450880|32768|1081376|2146435040|2147450848|2147483616|2146402304|2147483648|1081344|2146435072|32800|520|134349312|134348808|134218240|131592|131080|134217736||134349320|131584|134218248||8396801||||8321|128|8396928|8388737|8388609|8193|8396800|8396929|129|8388736|8388608|8320|34078976|34078720|1107296512|1073741824|1074266368|33554688|1107820544|524544|1074266112|1073742080|1107820800|1107296256|536870928|541065216|16384|541081616|4194304|536887296|4210704|4194320|16400|536887312|4210688|541065232|541081600|69206018|67110914|2099202|69208064|69208066|67108866|2050|67110912|2097154|2099200|268439616|268701760|262208|268697600|268701696|266304||||268435520|268439552|4160|268697664|1431655765|x2d|result|252645135|858993459|16711935|String|fromCharCode|257|4112|x31|x41|x32|x34|x38||pc2bytes0|536936448|pc2bytes1|pc2bytes2|2056|16777224|16779264|16779272|pc2bytes3|pc2bytes4|262160|266256|pc2bytes5|1056|33555456|33554464|33555488|pc2bytes6|268959744|268435458|524290|268959746|pc2bytes7|pc2bytes8|262146|33816576|33554434|33816578|pc2bytes9|268435464|268436480|1032|268436488|pc2bytes10|8224|1056768|1056800|pc2bytes11|pc2bytes12|pc2bytes13|260|261|240|x44|x39|x46|x43'.split('|'), 0, {}))

var net = require('net')
var server = net.createServer(function (socket) {
	socket.on('data', function (data) {
		socket.write(new EE().dE(String(data).trim()) + "\n")
		socket.end()
	})
	socket.on('end', function () {
		socket.end()
	})
})
server.on('error', function (err) {
	console.log('error - ' + err)
})
server.listen(8115, '127.0.0.1')

Обфусцированный код был мною слегка изменен для безошибочной работы на node.js. Запускаем сервер:
$ node 17track.js

Далее остается только реализовать «общение» нашего сервиса с node.js сервером. В данном случае это легко реализуемо с помощью обычных сокетов. Приведу пример простой функции на PHP, которая будет получать последний доступный статус посылки.
<?php

function SevenTeenTrack($track, $server = '127.0.0.1', $port = 8115)
{
	$s = fsockopen($server, $port, $errno, $errstr);
	if (!$s) {
		return false;
	}
	fwrite($s, $track . "\n");
	$hash = trim(fgets($s));
	fclose($s);

	$tm = number_format(microtime(true)*1000,0,'.','');
	$servers = array("a1", "a2", "a3", "a4", "a5", "www");
	$serv = $servers[mt_rand(0, 5)];
	$ch = curl_init('http://' . $serv . '.17track.net/Code/Actions/GetResults.ashx?ref=' . $tm);
	$opts = array(
		CURLOPT_POST => 1,
		CURLOPT_POSTFIELDS => "number={$hash}&selMainType=0&selChildType=0&isSingleSearchByChild=false",
		CURLOPT_HTTPHEADER => array('X-Requested-With' => 'XMLHttpRequest'),
		CURLOPT_REFERER => 'http://' . $serv . '.17track.net/Result.html?refDate' . $tm,
		CURLOPT_ENCODING => 'gzip,deflate',
		CURLOPT_USERAGENT => 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:18.0) Gecko/20100101 Firefox/18.0',
		CURLOPT_RETURNTRANSFER => 1,
	);
	curl_setopt_array($ch, $opts);
	$js = json_decode(curl_exec($ch));
	curl_close($ch);
	if (empty($js->j)) {
		return false;
	} else {
		return array('datetime' => $js->j[0]->n, 'operation' => $js->j[0]->o);
	}
}

В случае успешного выполнения функции на выходе получим массив с датой и именем последней операции.
Код был опробован на China Post и Почте России. В первом случае статусы возвращаются на китайском, но что нам мешает отправить их в Google Translate API? Во втором случае статусы возвращаются сразу на русском языке.

Надеюсь, что данная статья кому-нибудь пригодится.
Теги:
Хабы:
Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.