<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>https://fixme.ch/w/index.php?action=history&amp;feed=atom&amp;title=CTF%2Fgits2012teaser%2F2-ALsRevenge</id>
		<title>CTF/gits2012teaser/2-ALsRevenge - Revision history</title>
		<link rel="self" type="application/atom+xml" href="https://fixme.ch/w/index.php?action=history&amp;feed=atom&amp;title=CTF%2Fgits2012teaser%2F2-ALsRevenge"/>
		<link rel="alternate" type="text/html" href="https://fixme.ch/w/index.php?title=CTF/gits2012teaser/2-ALsRevenge&amp;action=history"/>
		<updated>2026-07-12T02:38:15Z</updated>
		<subtitle>Revision history for this page on the wiki</subtitle>
		<generator>MediaWiki 1.25.1</generator>

	<entry>
		<id>https://fixme.ch/w/index.php?title=CTF/gits2012teaser/2-ALsRevenge&amp;diff=1375&amp;oldid=prev</id>
		<title>Francois: Created page with &quot;== #2 AL's Revenge ==  === Question ===  Use your team GUID and generate a serial. (File)&lt;br&gt; Hint: [[Media:17b82879c583eeae763ecfa...&quot;</title>
		<link rel="alternate" type="text/html" href="https://fixme.ch/w/index.php?title=CTF/gits2012teaser/2-ALsRevenge&amp;diff=1375&amp;oldid=prev"/>
				<updated>2012-01-08T15:36:36Z</updated>
		
		<summary type="html">&lt;p&gt;Created page with &amp;quot;== #2 AL&amp;#039;s Revenge ==  === Question ===  Use your team GUID and generate a serial. (&lt;a href=&quot;/w/images/1/15/49dd327824d5afe9cdf931ea4b13719f.bin&quot; class=&quot;internal&quot; title=&quot;49dd327824d5afe9cdf931ea4b13719f.bin&quot;&gt;File&lt;/a&gt;)&amp;lt;br&amp;gt; Hint: [[Media:17b82879c583eeae763ecfa...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;== #2 AL's Revenge ==&lt;br /&gt;
&lt;br /&gt;
=== Question ===&lt;br /&gt;
&lt;br /&gt;
Use your team GUID and generate a serial. ([[Media:49dd327824d5afe9cdf931ea4b13719f.bin|File]])&amp;lt;br&amp;gt;&lt;br /&gt;
Hint: [[Media:17b82879c583eeae763ecfa9a135e431.cpp|File]]&lt;br /&gt;
&lt;br /&gt;
=== Solution ===&lt;br /&gt;
&lt;br /&gt;
* file [[Media:49dd327824d5afe9cdf931ea4b13719f.bin|49dd327824d5afe9cdf931ea4b13719f.bin]] says xz compressed file -&amp;gt; xzcat &amp;gt; f&lt;br /&gt;
* file f says LLVM bitcode -&amp;gt; llvm-dis &amp;gt; f.s (only works with LLVM 2.8, not with 3.0)&lt;br /&gt;
* analyze disassembly, extract C representation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
int&lt;br /&gt;
VerifySerial(uint64_t name, uint64_t serial)&lt;br /&gt;
{&lt;br /&gt;
	uint64_t a = 0x8000000000000000LL;&lt;br /&gt;
        uint64_t b = 0xa348fccd93aea5a7LL;&lt;br /&gt;
	uint64_t result = 0;&lt;br /&gt;
&lt;br /&gt;
	/* high order bit set? */&lt;br /&gt;
	if (name &amp;amp; a)&lt;br /&gt;
		a ^= b;&lt;br /&gt;
&lt;br /&gt;
	if (serial &amp;amp; a)&lt;br /&gt;
		serial ^= b;&lt;br /&gt;
&lt;br /&gt;
	while (serial != 0) {&lt;br /&gt;
		if (serial &amp;amp; 1)&lt;br /&gt;
			result ^= name;&lt;br /&gt;
&lt;br /&gt;
		serial &amp;gt;&amp;gt;= 1;&lt;br /&gt;
		name &amp;lt;&amp;lt;= 1;&lt;br /&gt;
&lt;br /&gt;
		if (name &amp;amp; a)&lt;br /&gt;
			name ^= b;&lt;br /&gt;
	}H&lt;br /&gt;
&lt;br /&gt;
	return (result == 1);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* it looks like a multiplication over a galois field, with the irreducible polynomial 0x1a348fccd93aea5a7 (note leading bit not in C), but it actually isn't, because the high bit gets checked after the shift, not before.&lt;br /&gt;
* lacking math knowledge and math package fu, decided to treat the problem as a linear equation system:&lt;br /&gt;
* The shifting and xoring produces a set of integers, call them name_i.  If the serial bit s_i is set, name_i gets added to the result.  So you can roughly say r = N * s, with r being the result vector, s the serial vector and N the names matrix.&lt;br /&gt;
* lacking math package fu, implement a gaussian elimination manually:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ruby&amp;quot;&amp;gt;&lt;br /&gt;
class Numeric&lt;br /&gt;
  def bits64&lt;br /&gt;
    sprintf(&amp;quot;%064b&amp;quot;, self).each_char.map{|c| c == &amp;quot;0&amp;quot; ? 0 : 1}&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
def names(name)&lt;br /&gt;
  p = 0xa348fccd93aea5a7&lt;br /&gt;
&lt;br /&gt;
  if (name &amp;gt;&amp;gt; 63) &amp;amp; 1 == 1&lt;br /&gt;
    name ^= p&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  ([name] + 63.times.map do |i|&lt;br /&gt;
    name &amp;lt;&amp;lt;= 1&lt;br /&gt;
    if (name &amp;gt;&amp;gt; 63) &amp;amp; 1 == 1&lt;br /&gt;
      name ^= p&lt;br /&gt;
    end&lt;br /&gt;
    name&lt;br /&gt;
  end).map(&amp;amp;:bits64)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class Array&lt;br /&gt;
  def pivot&lt;br /&gt;
    res = []&lt;br /&gt;
    self[0].size.times.map do |i|&lt;br /&gt;
      self.size.times.map do |j|&lt;br /&gt;
        self[j][i]&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def bitary_to_int&lt;br /&gt;
    self.join.to_i(2)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class Eq &amp;lt; Array&lt;br /&gt;
  attr_accessor :res&lt;br /&gt;
&lt;br /&gt;
  def initialize(ary, res)&lt;br /&gt;
    self.replace(ary)&lt;br /&gt;
    @res = res&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def lead_zero&lt;br /&gt;
    self.take_while{|e| e == 0}&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def first_pos&lt;br /&gt;
    self.index(1)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def subtract(o)&lt;br /&gt;
    Eq.new(self.zip(o).map{|aa, bb| aa ^ bb}, @res ^ o.res)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
class EqSys &amp;lt; Array&lt;br /&gt;
  def initialize(ary, res=nil)&lt;br /&gt;
    if !(Eq === ary[0]) &amp;amp;&amp;amp; !ary.empty?&lt;br /&gt;
      ary = ary.zip(res).map{|a, r| Eq.new(a, r)}&lt;br /&gt;
    end&lt;br /&gt;
    self.replace(ary)&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def sort_by_zeros&lt;br /&gt;
    self.sort do |a, b|&lt;br /&gt;
      a.lead_zero &amp;lt;=&amp;gt; b.lead_zero&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def subtract_eq(eq)&lt;br /&gt;
    pos = eq.first_pos&lt;br /&gt;
    return self if not pos&lt;br /&gt;
    EqSys.new(self.map{|e| e[pos] == 1 ? e.subtract(eq) : e})&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def elim&lt;br /&gt;
    front = EqSys.new([])&lt;br /&gt;
    cur = nil&lt;br /&gt;
    rest = self.sort_by_zeros&lt;br /&gt;
    while not rest.empty?&lt;br /&gt;
      front &amp;lt;&amp;lt; cur if cur&lt;br /&gt;
      cur = rest.shift&lt;br /&gt;
&lt;br /&gt;
      front = front.subtract_eq(cur)&lt;br /&gt;
      rest = rest.subtract_eq(cur)&lt;br /&gt;
      rest = rest.sort_by_zeros&lt;br /&gt;
    end&lt;br /&gt;
    front &amp;lt;&amp;lt; cur&lt;br /&gt;
&lt;br /&gt;
    front&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  def to_s&lt;br /&gt;
    self.map{|e| e.map(&amp;amp;:to_s).join + &amp;quot; = #{e.res}&amp;quot;}.join(&amp;quot;\n&amp;quot;)&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
require 'pp'&lt;br /&gt;
if __FILE__ == $0&lt;br /&gt;
  ns = names(0x6638623261336134)&lt;br /&gt;
&lt;br /&gt;
  pv = ns.pivot&lt;br /&gt;
  es = EqSys.new(pv, 1.bits64)&lt;br /&gt;
&lt;br /&gt;
  puts es.to_s&lt;br /&gt;
  puts&lt;br /&gt;
&lt;br /&gt;
  r = es.elim&lt;br /&gt;
  puts r.to_s&lt;br /&gt;
&lt;br /&gt;
  res = r.map{|e| e.res}.reverse&lt;br /&gt;
  puts res.bitary_to_int.to_s(16)&lt;br /&gt;
&lt;br /&gt;
  s0 = r.pivot.last.reverse&lt;br /&gt;
  puts s0.bitary_to_int.to_s(16)&lt;br /&gt;
  puts (res.bitary_to_int^s0.bitary_to_int).to_s(16)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Francois</name></author>	</entry>

	</feed>