Pull to refresh

Автоматизированное отслеживание посылок на основе 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? Во втором случае статусы возвращаются сразу на русском языке.

Надеюсь, что данная статья кому-нибудь пригодится.
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.