Pages

Monday, September 24, 2012

700 ipads in the district, and only one ios6 update to do.

Do we download it 700 times, or do we download it once, and send it out 700 times? Step 1 was hijacking DNS so that appldnld.apple.com was pointed to an internal server. Looking at the logs for apache we see that it's requesting something from the iOS6 folder.

10.100.69.20 - - [24/Sep/2012:18:59:40 -0400] "GET /iOS6/Documentation/041-6937.201209
19.55zYB/com_apple_MobileAsset_SoftwareUpdateDocumentation/1cb29d3c6a86fa0c11d099917f7
f4f10d28e40e9.zip HTTP/1.1" 200 574794847 "-" "iTunes-iPad/5.1.1 (2; 16GB; dt:74)"

10.100.153.89 - - [24/Sep/2012:21:11:40 -0400] "HEAD /iOS6/Documentation/041-6937.2012
0919.55zYB/com_apple_MobileAsset_SoftwareUpdateDocumentation/1cb29d3c6a86fa0c11d099917
f7f4f10d28e40e9.zip HTTP/1.1" 200 323 "-" "iTunes-iPad/5.1.1 (2; 16GB; dt:74)"

10.100.153.89 - - [24/Sep/2012:21:11:40 -0400] "GET /iOS6/Documentation/041-6937.20120
919.55zYB/com_apple_MobileAsset_SoftwareUpdateDocumentation/1cb29d3c6a86fa0c11d099917f
7f4f10d28e40e9.zip HTTP/1.1" 200 574794847 "-" "iTunes-iPad/5.1.1 (2; 16GB; dt:74)"

10.101.133.79 - - [24/Sep/2012:21:45:32 -0400] "HEAD /iOS6/Documentation/041-6937.2012
0919.55zYB/com_apple_MobileAsset_SoftwareUpdateDocumentation/1cb29d3c6a86fa0c11d099917
f7f4f10d28e40e9.zip HTTP/1.1" 200 323 "-" "iTunes-iPad/5.1.1 (2; 16GB; dt:74)"

10.101.133.79 - - [24/Sep/2012:21:45:32 -0400] "GET /iOS6/Documentation/041-6937.20120
919.55zYB/com_apple_MobileAsset_SoftwareUpdateDocumentation/1cb29d3c6a86fa0c11d099917f
7f4f10d28e40e9.zip HTTP/1.1" 200 574794847 "-" "iTunes-iPad/5.1.1 (2; 16GB; dt:74)"
 
  So what now? Well, we need to know the User Agent (check!) and what variables are passed as headers and what cookie values are passed.
 $fp = fopen("/var/www/iOS6/log.txt", w);

 foreach ($_GET as $var=>$value) {
  $tmpLine = $var."=".$value."\n";

  fputs($fp, $tmpLine, strlen($tmpLine));
 }
 fputs($fp, "EOG-\n", 5);


 foreach ($_POST as $var=>$value) {
  $tmpLine = $var."=".$value."\n";

  fputs($fp, $tmpLine, strlen($tmpLine));
 }
 fputs($fp, "EOP-\n", 5);

 foreach ($_SERVER as $var=>$value) {
  $tmpLine = $var."=".$value."\n";

  fputs($fp, $tmpLine, strlen($tmpLine));
 }
 fputs($fp, "EOS-\n", 5);
 foreach ($_COOKIE as $var=>$value) {
  $tmpLine = $var."=".$value."\n";

  fputs($fp, $tmpLine, strlen($tmpLine));
 }
 fputs($fp, "EOC-\n", 5);

 fclose($fp);

?>
This does it, but I had to redirect everything to it and it alone... Mod-Rewrite to the rescue!
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php [L,QSA]
So now http://<apache>/iOS6/sjdfhksjdhfksdhfkjsdhf is rewrote straight to index.php. Let's look at log.txt from an iPad request --
q=041-7072.20120901.cfbLY/com_apple_MobileAsset_SoftwareUpdate/250dc5a5ec8dbb05f0f9ae
2e28a4074238509bf1.zip
EOG-
EOP-
REDIRECT_STATUS=200
HTTP_HOST=appldnld.apple.com
HTTP_USER_AGENT=iTunes-iPad/5.1.1 (2; 16GB; dt:74)
HTTP_ACCEPT=*/*
HTTP_COOKIE=TrPod=2; X-Dsid=213655354; NSC_JOr1rhwld4dgcvwckxmrdtdtcz21wbq=ffffffff12
923db245525d5f4f58455e445a4a423660; mz_at0=AwQAAAFKAADDtQAAAABQPmH4VMzDTLLoXGWetSyEZt
RBPhe45DY=; Pod=20; s_vi=[CS]v1|281F30F305013F7B-60000106A00F0A64[CE]
HTTP_ACCEPT_LANGUAGE=en;q=1.0,fr;q=1.0,de;q=0.9,ja;q=0.9,nl;q=0.9,it;q=0.9,es;q=0.8,p
t;q=0.8,pt-PT;q=0.8,da;q=0.7,fi;q=0.7,nb;q=0.7,sv;q=0.7,ko;q=0.6,zh-Hans;q=0.6,zh-Han
t;q=0.6,ru;q=0.5,pl;q=0.5,tr;q=0.5,uk;q=0.5,ar;q=0.4,hr;q=0.4,cs;q=0.4,el;q=0.3,he;q=
0.3,ro;q=0.3,sk;q=0.3,th;q=0.2,id;q=0.2,ms;q=0.2,en-GB;q=0.1,ca;q=0.1,hu;q=0.1,vi;q=0.1
HTTP_RANGE=bytes=18764202-
HTTP_ACCEPT_ENCODING=gzip, deflate
HTTP_CONNECTION=keep-alive
PATH=/usr/local/bin:/usr/bin:/bin
SERVER_SIGNATURE=
Apache/2.2.17 (Ubuntu) Server at appldnld.apple.com Port 80
SERVER_SOFTWARE=Apache/2.2.17 (Ubuntu) SERVER_NAME=appldnld.apple.com SERVER_ADDR=10.101.2.20 SERVER_PORT=80 REMOTE_ADDR=10.101.131.254 DOCUMENT_ROOT=/var/www SERVER_ADMIN=webmaster@localhost SCRIPT_FILENAME=/var/www/iOS6/index.php REMOTE_PORT=49162 REDIRECT_QUERY_STRING=q=041-7072.20120901.cfbLY/com_apple_MobileAsset_SoftwareUpdate/ 250dc5a5ec8dbb05f0f9ae2e28a4074238509bf1.zip REDIRECT_URL=/iOS6/041-7072.20120901.cfbLY/com_apple_MobileAsset_SoftwareUpdate/250dc 5a5ec8dbb05f0f9ae2e28a4074238509bf1.zip GATEWAY_INTERFACE=CGI/1.1 SERVER_PROTOCOL=HTTP/1.1 REQUEST_METHOD=GET QUERY_STRING=q=041-7072.20120901.cfbLY/com_apple_MobileAsset_SoftwareUpdate/250dc5a5e c8dbb05f0f9ae2e28a4074238509bf1.zip REQUEST_URI=/iOS6/041-7072.20120901.cfbLY/com_apple_MobileAsset_SoftwareUpdate/250dc5 a5ec8dbb05f0f9ae2e28a4074238509bf1.zip SCRIPT_NAME=/iOS6/index.php PHP_SELF=/iOS6/index.php REQUEST_TIME=1348506471 EOS- TrPod=2 X-Dsid=213655354 NSC_JOr1rhwld4dgcvwckxmrdtdtcz21wbq=ffffffff12923db245525d5f4f58455e445a4a423660 mz_at0=AwQAAAFKAADDtQAAAABQPmH4VMzDTLLoXGWetSyEZtRBPhe45DY= Pod=20 s_vi=[CS]v1|281F30F305013F7B-60000106A00F0A64[CE] EOC-
-- I'm sure this means something to apple, but I'm interested in the headers at the top (before EOS) and the cookies at the bottom (before EOC) I put the cookies in the jar, before this process can get very far! cookies.txt --
TrPod=2
X-Dsid=213655354
NSC_JOr1rhwld4dgcvwckxmrdtdtcz21wbq=ffffffff12923db245525d5f4f58455e445a4a423660
mz_at0=AwQAAAFKAADDtQAAAABQPmH4VMzDTLLoXGWetSyEZtRBPhe45DY=
Pod=20
s_vi=[CS]v1|281F30F305013F7B-60000106A00F0A64[CE]
-- And then? I download the update..
/var/www/iOS6# wget --load-cookies=cookies.txt "http://appldnld.apple.com/iOS6/041-70
72.20120901.cfbLY/com_apple_MobileAsset_SoftwareUpdate/250dc5a5ec8dbb05f0f9ae2e28a407
4238509bf1.zip?q=041-7072.20120901.cfbLY/com_apple_MobileAsset_SoftwareUpdate/250dc5a
5ec8dbb05f0f9ae2e28a4074238509bf1.zip" -U "iTunes-iPad/5.1.1 (2; 16GB; dt:74)"

--2012-09-24 12:24:29--  http://appldnld.apple.com/iOS6/041-7072.20120901.cfbLY/com_a
pple_MobileAsset_SoftwareUpdate/250dc5a5ec8dbb05f0f9ae2e28a4074238509bf1.zip?q=041-70
72.20120901.cfbLY/com_apple_MobileAsset_SoftwareUpdate/250dc5a5ec8dbb05f0f9ae2e28a407
4238509bf1.zip

Resolving appldnld.apple.com... 4.27.26.254

Connecting to appldnld.apple.com|4.27.26.254|:80... connected.

HTTP request sent, awaiting response... 200 OK

Length: 574794525 (548M) [application/octet-stream]

Saving to: `250dc5a5ec8dbb05f0f9ae2e28a4074238509bf1.zip?q=041-7072.20120901.cfbLY%2F
com_apple_MobileAsset_SoftwareUpdate%2F250dc5a5ec8dbb05f0f9ae2e28a4074238509bf1.zip'

12:31

11% [==================>                 ] 65,058,644   427K/s  eta 33m 4s  

What now you say? Uhhhh How about sharing it back out for everyone else requesting it?!

Added the following lines to the bottom of index.php

--

 $tmpFields = split("\/", $_SERVER["REQUEST_URI"]);
 $tmpMax = count($tmpFields);
 $tmpFilename = $tmpFields[$tmpMax-1];


 header("Pragma: public");
 header('Content-disposition: attachment; filename='.$tmpFilename);
 header("Content-type: ".mime_content_type("/var/www/iOS6/update.zip"));
 header('Content-Transfer-Encoding: binary');
 ob_clean();
 flush();
 readfile("/var/www/iOS6/update.zip");


--



And that of course, sends the headers that a file is coming, and it's name is the same
 name as requested, but of course it's my update.zip.

Later on, I got tired of collecting logs so just redirected everyone to my update.zip


--
 
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ update.zip [L,QSA]
-- Now the fun part, this update.zip is just a plain vanilla zip... I extracted it and you just see the iPad binarys, images, etc. I'm not sure this is helpful in any means (I'm sure apple CRC's the update before applying it) but it was shocking that this isn't some passworded DMG or something of the like.
Oh well I had fun.. Hopefully you had fun reading!