|
|
| (21 intermediate revisions by 3 users not shown) |
| Line 1: |
Line 1: |
| − | == #1 TelAviv ==
| + | [[Category:CTF]] |
| | + | [[Image:gits-scores.png]] |
| | | | |
| − | What is the password? ([[File:7139a4ea239dcac655f7c38ca6a77b61.bin|File]])<br>
| + | = Ghost in the Shellcode 2012 Teasers writeups = |
| − | Hint: TeLaViv+ is a packet forensics challenge.
| + | |
| | | | |
| − | == #2 AL's Revenge ==
| + | http://ghostintheshellcode.com/ |
| | | | |
| − | * file 49dd327824d5afe9cdf931ea4b13719f.bin says xz compressed file -> xzcat > f
| + | Thanks to the organizers for those pretty nice teasers! |
| − | * file f says LLVM bitcode -> llvm-dis > f.s (only works with LLVM 2.8, not with 3.0)
| + | |
| − | * analyze disassembly, extract C representation:
| + | |
| | | | |
| − | <pre>
| + | The following writeups have been made by members of the FIXME team during between January 6th and January 8th. |
| − | int
| + | |
| − | VerifySerial(uint64_t name, uint64_t serial)
| + | |
| − | {
| + | |
| − | uint64_t a = 0x8000000000000000LL;
| + | |
| − | uint64_t b = 0xa348fccd93aea5a7LL;
| + | |
| − | uint64_t result = 0;
| + | |
| | | | |
| − | /* high order bit set? */
| + | * Challenge [[CTF/gits2012teaser/1-TelAviv|#1 TelAviv]] by [[User:Francois|Francois]] |
| − | if (name & a)
| + | * Challenge [[CTF/gits2012teaser/2-ALsRevenge|#2 AL's Revenge]] by [[User:Corecode|Corecode]] |
| − | a ^= b;
| + | * Challenge [[CTF/gits2012teaser/3-Hackquest|#3 Hackquest]] by [[User:Corecode|Corecode]] |
| − | | + | |
| − | if (serial & a)
| + | |
| − | serial ^= b;
| + | |
| − | | + | |
| − | while (serial != 0) {
| + | |
| − | if (serial & 1)
| + | |
| − | result ^= name;
| + | |
| − | | + | |
| − | serial >>= 1;
| + | |
| − | name <<= 1;
| + | |
| − | | + | |
| − | if (name & a)
| + | |
| − | name ^= b;
| + | |
| − | }H
| + | |
| − | | + | |
| − | return (result == 1);
| + | |
| − | }
| + | |
| − | </pre>
| + | |
| − | | + | |
| − | * 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.
| + | |
| − | * lacking math knowledge and math package fu, decided to treat the problem as a linear equation system:
| + | |
| − | * 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.
| + | |
| − | * lacking math package fu, implement a gaussian elimination manually:
| + | |
| − | | + | |
| − | <pre>
| + | |
| − | class Numeric
| + | |
| − | def bits64
| + | |
| − | sprintf("%064b", self).each_char.map{|c| c == "0" ? 0 : 1}
| + | |
| − | end
| + | |
| − | end
| + | |
| − | | + | |
| − | def names(name)
| + | |
| − | p = 0xa348fccd93aea5a7
| + | |
| − | | + | |
| − | if (name >> 63) & 1 == 1
| + | |
| − | name ^= p
| + | |
| − | end
| + | |
| − | | + | |
| − | ([name] + 63.times.map do |i|
| + | |
| − | name <<= 1
| + | |
| − | if (name >> 63) & 1 == 1
| + | |
| − | name ^= p
| + | |
| − | end
| + | |
| − | name
| + | |
| − | end).map(&:bits64)
| + | |
| − | end
| + | |
| − | | + | |
| − | class Array
| + | |
| − | def pivot
| + | |
| − | res = []
| + | |
| − | self[0].size.times.map do |i|
| + | |
| − | self.size.times.map do |j|
| + | |
| − | self[j][i]
| + | |
| − | end
| + | |
| − | end
| + | |
| − | end
| + | |
| − | | + | |
| − | def bitary_to_int
| + | |
| − | self.join.to_i(2)
| + | |
| − | end
| + | |
| − | end
| + | |
| − | | + | |
| − | class Eq < Array
| + | |
| − | attr_accessor :res
| + | |
| − | | + | |
| − | def initialize(ary, res)
| + | |
| − | self.replace(ary)
| + | |
| − | @res = res
| + | |
| − | end
| + | |
| − | | + | |
| − | def lead_zero
| + | |
| − | self.take_while{|e| e == 0}
| + | |
| − | end
| + | |
| − | | + | |
| − | def first_pos
| + | |
| − | self.index(1)
| + | |
| − | end
| + | |
| − | | + | |
| − | def subtract(o)
| + | |
| − | Eq.new(self.zip(o).map{|aa, bb| aa ^ bb}, @res ^ o.res)
| + | |
| − | end
| + | |
| − | end
| + | |
| − | | + | |
| − | class EqSys < Array
| + | |
| − | def initialize(ary, res=nil)
| + | |
| − | if !(Eq === ary[0]) && !ary.empty?
| + | |
| − | ary = ary.zip(res).map{|a, r| Eq.new(a, r)}
| + | |
| − | end
| + | |
| − | self.replace(ary)
| + | |
| − | end
| + | |
| − | | + | |
| − | def sort_by_zeros
| + | |
| − | self.sort do |a, b|
| + | |
| − | a.lead_zero <=> b.lead_zero
| + | |
| − | end
| + | |
| − | end
| + | |
| − | | + | |
| − | def subtract_eq(eq)
| + | |
| − | pos = eq.first_pos
| + | |
| − | return self if not pos
| + | |
| − | EqSys.new(self.map{|e| e[pos] == 1 ? e.subtract(eq) : e})
| + | |
| − | end
| + | |
| − | | + | |
| − | def elim
| + | |
| − | front = EqSys.new([])
| + | |
| − | cur = nil
| + | |
| − | rest = self.sort_by_zeros
| + | |
| − | while not rest.empty?
| + | |
| − | front << cur if cur
| + | |
| − | cur = rest.shift
| + | |
| − | | + | |
| − | front = front.subtract_eq(cur)
| + | |
| − | rest = rest.subtract_eq(cur)
| + | |
| − | rest = rest.sort_by_zeros
| + | |
| − | end
| + | |
| − | front << cur
| + | |
| − | | + | |
| − | front
| + | |
| − | end
| + | |
| − | | + | |
| − | def to_s
| + | |
| − | self.map{|e| e.map(&:to_s).join + " = #{e.res}"}.join("\n")
| + | |
| − | end
| + | |
| − | end
| + | |
| − | | + | |
| − | require 'pp'
| + | |
| − | if __FILE__ == $0
| + | |
| − | ns = names(0x6638623261336134)
| + | |
| − | | + | |
| − | pv = ns.pivot
| + | |
| − | es = EqSys.new(pv, 1.bits64)
| + | |
| − | | + | |
| − | puts es.to_s
| + | |
| − | puts
| + | |
| − | | + | |
| − | r = es.elim
| + | |
| − | puts r.to_s
| + | |
| − | | + | |
| − | res = r.map{|e| e.res}.reverse
| + | |
| − | puts res.bitary_to_int.to_s(16)
| + | |
| − | | + | |
| − | s0 = r.pivot.last.reverse
| + | |
| − | puts s0.bitary_to_int.to_s(16)
| + | |
| − | puts (res.bitary_to_int^s0.bitary_to_int).to_s(16)
| + | |
| − | end
| + | |
| − | </pre>
| + | |
| − | | + | |
| − | == #3 Hackquest ==
| + | |
The following writeups have been made by members of the FIXME team during between January 6th and January 8th.