#!/usr/bin/env ruby
#
# Copyright (c) 2007, Gregory Fleischer (gfleischer@gmail.com)
# License: Revised BSD
#
# confoonu.rb -
# take two web pages and create two new web pages that have the same MD5 sum
# optionally, you can specify an additional web page that is used as the default when no javascript is used
# based on confoo.pl by Dan Kaminsky (www.doxpara.com/research/md5/confoo.pl)
#
require 'uri'
require 'net/http'
####
def readPage(page)
if page =~ /^http:\/\//i
readWeb(page)
else
readLocal(page)
end
end
def readWeb(page)
uri = URI.parse(page)
res = Net::HTTP.start(uri.host, uri.port) { |http|
http.get(uri.path)
}
body = res.body
base_href = ""
if body =~ /(]*>)/i
base_href = $1
end
body.sub!(/^.*/mi, "")
body.sub!(/<\/html[^<]*>.*$/mi, "")
if body !~ //i
body.sub!(/
/i) { |m| "#{m}#{base_href}" }
elsif body =~ /#{base_href}#{m}" }
else
body = "#{base_href}" + body
end
end
body
end
def readLocal(page)
data = []
File.foreach(page) { |line| data << line}
data.join
end
def makeFile(file, num, page1, page2, defaultpage)
prefix = [
0x3C,0x68,0x74,0x6D,0x6C,0x3E,0x20,0x20,0x0A,0x20,0x3C,0x73,0x63,0x72,0x69,0x70,
0x74,0x3E,0x20,0x0A,0x20,0x3C,0x21,0x2D,0x2D,0x20,0x2F,0x2F,0x20,0x68,0x69,0x64,
0x65,0x20,0x6A,0x61,0x76,0x61,0x73,0x63,0x72,0x69,0x70,0x74,0x0A,0x20,0x20,0x20,
0x76,0x61,0x72,0x20,0x5F,0x5F,0x76,0x65,0x63,0x74,0x6F,0x72,0x20,0x3D,0x20,0x22,
]
vectors = [
# 1
[
0xCF,0xB2,0xB8,0x8C,0x08,0xCE,0x55,0xD4,0x58,0x6A,0x9C,0x23,0x27,0xFF,0x7E,0xDC,
0x4E,0xC2,0xC5,0xB3,0xF4,0x86,0x27,0xFF,0x52,0xAF,0x3A,0x17,0x40,0xA7,0x62,0xD5,
0x55,0x2D,0x34,0x06,0x05,0x64,0x34,0x04,0x57,0xE7,0xB0,0x79,0xE7,0xE4,0x29,0x94,
0xDE,0x16,0x5F,0xC7,0xDA,0xD1,0xDA,0xFD,0xE8,0xB7,0x63,0xF8,0x56,0xF9,0x49,0xFD,
0x41,0xF9,0x74,0xBE,0xE0,0x65,0xDB,0x33,0xA5,0x14,0x88,0x2B,0xE1,0x9E,0x60,0xDB,
0xCA,0xF7,0xE2,0x16,0x8C,0x47,0x48,0x1E,0xF2,0xE8,0xE6,0xF7,0x4A,0xDB,0xDD,0xCE,
0xFD,0x6E,0x37,0x2F,0xCA,0xB6,0x23,0x07,0xFA,0xE9,0x49,0x4A,0x93,0x28,0xA5,0x5C,
0x0E,0x85,0x7B,0xA3,0xD2,0xA4,0x9B,0x8B,0x78,0xF8,0x88,0x1C,0x2F,0x59,0xD5,0x78,
],
# 2
[
0xCF,0xB2,0xB8,0x8C,0x08,0xCE,0x55,0xD4,0x58,0x6A,0x9C,0x23,0x27,0xFF,0x7E,0xDC,
0x4E,0xC2,0xC5,0x33,0xF4,0x86,0x27,0xFF,0x52,0xAF,0x3A,0x17,0x40,0xA7,0x62,0xD5,
0x55,0x2D,0x34,0x06,0x05,0x64,0x34,0x04,0x57,0xE7,0xB0,0x79,0xE7,0x64,0x2A,0x94,
0xDE,0x16,0x5F,0xC7,0xDA,0xD1,0xDA,0xFD,0xE8,0xB7,0x63,0x78,0x56,0xF9,0x49,0xFD,
0x41,0xF9,0x74,0xBE,0xE0,0x65,0xDB,0x33,0xA5,0x14,0x88,0x2B,0xE1,0x9E,0x60,0xDB,
0xCA,0xF7,0xE2,0x96,0x8C,0x47,0x48,0x1E,0xF2,0xE8,0xE6,0xF7,0x4A,0xDB,0xDD,0xCE,
0xFD,0x6E,0x37,0x2F,0xCA,0xB6,0x23,0x07,0xFA,0xE9,0x49,0x4A,0x93,0xA8,0xA4,0x5C,
0x0E,0x85,0x7B,0xA3,0xD2,0xA4,0x9B,0x8B,0x78,0xF8,0x88,0x9C,0x2F,0x59,0xD5,0x78,
]
]
vector = vectors[num-1]
prefix.each {|b| file.putc b}
vector.each {|b| file.putc b}
file << "\";\n"
# add the script to build the page
file << " var __v1 = \""
vectors[0].each {|b| file.putc b}
file << "\";\n"
file << " var __v2 = \""
vectors[1].each {|b| file.putc b}
file << "\";\n"
file << " var __t1 = \""
file << page1.gsub(/[^a-zA-Z0-9]/) {|c| "%%%02X" % c[0]}
file << "\";\n"
file << " var __t2 = \""
file << page2.gsub(/[^a-zA-Z0-9]/) {|c| "%%%02X" % c[0]}
file << "\";\n"
file << " var __df = \""
if defaultpage
file << defaultpage.gsub(/[^a-zA-Z0-9]/) {|c| "%%%02X" % c[0]}
end
file << "\";\n"
# add the logic to build the page on the fly
file << %[
var index = 0;
if (__vector == __v1) {
index = 1;
} else if (__vector == __v2) {
index = 2;
}
if (0 != index) {
try {
var body = document.body;
if (body) {
body.innerHTML = "";
var g = 0;
while (body.attributes.length > 0 && (++g < 256)) {
body.attributes.removeNamedItem(body.attributes[0].nodeName);
}
}
var head = document.getElementsByTagName("HEAD")[0];
if (head) {
try {
head.innerHTML = "";
} catch(e) {
}
}
} catch (e) {}
}
if (1 == index) {
document.write(unescape(__t1));
} else if (2 == index) {
document.write(unescape(__t2));
} else {
document.write(unescape(__df));
}
]
file << "\n//-->\n"
file << "\n"
file << "\n"
file << "\n\n"
end
####
if ARGV.length < 2
puts "usage: confoonu.rb [defaultpage]"
exit 1
end
page1 = readPage(ARGV[0])
page2 = readPage(ARGV[1])
defaultpage = nil
if ARGV.length > 2
defaultpage = readPage(ARGV[2])
end
File.open("t1.html", 'w') { |file|
makeFile(file, 1, page1, page2, defaultpage)
}
File.open("t2.html", 'w') { |file|
makeFile(file, 2, page1, page2, defaultpage)
}
exit 0
# eof