ログイン
編集不可のページディスカッション情報添付ファイル
"CTF/Writeup/tkbctf4/amida"の差分

MMA
1と3のリビジョン間の差分 (その間の編集: 2回)
2014-11-03 21:42:02時点のリビジョン1
サイズ: 22
編集者: ytoku
コメント:
2014-11-04 18:32:34時点のリビジョン3
サイズ: 8451
編集者: nomeaning
コメント:
削除された箇所はこのように表示されます。 追加された箇所はこのように表示されます。
行 2: 行 2:
黒丸を高さ470の所になるまで回転させ、位置を補正して、あみだくじをパースした。

本番中はフラグ2まで、終了後同じプログラムでフラグ3を、数行改変することでフラグ4を得ることが出来た。
{{{#!highlight ruby
require_relative 'ctf'
require 'RMagick'
require 'base64'
include Magick

def common_stage(s, base64, n, w)
  File.binwrite('/tmp/tmp.png', Base64.decode64(base64))
  img = ImageList.new('/tmp/tmp.png')
  mp = []
  (150...450).step(2).each.with_index do |y,i|
    mp <<= []
    (n - 1).times do |x|
      if img.pixel_color((x+1) * w + w / 2, y).red == 0
        mp[-1] << [x+1,x+2]
      end
    end
  end
  mp.delete_if {|a| a == [] }
  target = [*0...n].find{|i| img.pixel_color( ( i + 1 ) * w, 470).red == 0 }
  current = target + 1
  mp.reverse.each do |arr|
    arr.each do |x,y|
      if x == current
        current = y
      elsif y == current
        current = x
      end
    end
  end
  s.puts current
  s.puts
end

def common_stage2(s, base64, n)
  File.binwrite('/tmp/tmp.png', Base64.decode64(base64))
  img = ImageList.new('/tmp/tmp.png')
  mp = []
  (150...450).each.with_index do |y,i|
    mp <<= []
    (n - 1).times do |x|
      if img.pixel_color((x+1) * 600 / (n + 1) + 1, y).red <= 3*257
        next if mp.size >= 2 && mp[-2].include?([x+1,x+2])
        mp[-1] << [x+1,x+2]
      end
    end
  end
  mp.delete_if {|a| a == [] }
  target = [*0...n].find{|i| img.pixel_color( 600 * ( i + 1 ) / (n + 1), 470).red == 0 }
  p mp
  current = target + 1
  mp.reverse.each do |arr|
    p current
    arr.each do |x,y|
      if x == current
        current = y
      elsif y == current
        current = x
      end
    end
  end
  s.puts current
  s.puts
end

require 'matrix'
def common_stage3(s, filename, n)
  def rotate(x,y,angle)
    y = 600 - y
    angle = -angle
    x,y = x - 300, y - 300
    nx = x * Math::cos(angle) - y * Math::sin(angle)
    ny = x * Math::sin(angle) + y * Math::cos(angle)
    return nx + 300, 600 - (ny + 300)
  end
  def dot(x1,y1,x2,y2)
    x1.to_f*x2.to_f+y1.to_f*y2.to_f
  end
  def norm(x,y)
    x * x.to_f + y * y.to_f
  end
  def projection(l, p)
    p l
    t = dot(p[0]-l[0][0],p[1]-l[0][1],l[1][0] - l[0][0], l[1][1] - l[0][1]) / norm(l[0][0] - l[1][0], l[0][1] - l[1][1])
    [l[0][0] + (l[1][0] - l[0][0]) * t, l[0][1] + (l[1][1] - l[0][1]) * t]
  end
  img = ImageList.new(filename)
  cx,cy=nil,nil
  img.rows.times do |y|
    break if cx
    img.columns.times do |x|
      next unless img.pixel_color(x,y).red == 0
      ok = true
      (-1..1).each do |dx|
        (-1..1).each do |dy|
          ok = false if img.pixel_color(x + dx * 5, y + dy * 5).red != 0
        end
      end
      if ok
        # found
        cx, cy = x,y
        break
      end
    end
  end
  p ["Circle:", cx, cy]
  r = Math::sqrt((300 - cx) ** 2 + (300 - cy) ** 2)
  angle = Math::atan2(-cy + 300, cx - 300) + Math::PI / 2
  angle2=nil
  if r >= 170
  angle2 = Math::atan2(Math::sqrt(r*r-170*170),170)
  else
    angle2 = 0
  end
  p angle / Math::PI * 180
  p angle / Math::PI * 180
  p rotate(cx,cy,angle)
  p 'rotate2'
  p (angle + angle2) / Math::PI * 180
  p rotate(cx,cy,angle + angle2)
  angle += angle2
  ys = [200, 250]
  xs = ys.map{|y|
    img.columns.times.to_a.index do |x|
      img.pixel_color(*rotate(x,y,-angle)).red <= 127 * 257
    end
  }
  p xs
  dsum = if !xs[1] || !xs[0]
           9999999
         else
           wt = 600 / (n + 1)
           (xs[0] - wt).abs + (xs[1] - wt).abs
         end
  p 'next try'
  p (angle) / Math::PI * 180
  fxs = xs + []
  angle -= angle2 * 2
  xs = ys.map{|y|
    img.columns.times.to_a.index do |x|
      img.pixel_color(*rotate(x,y,-angle)).red <= 127 * 257
    end
  }
  p xs
  qsum = if !xs[1] || !xs[0]
           9999999
         else
           wt = 600 / (n + 1)
           (xs[0] - wt).abs + (xs[1] - wt).abs
         end
  p ['first', dsum]
  p ['first', qsum]
  if dsum < qsum
    p 'use first'
    xs = fxs
    angle += angle2 * 2
  else
    p 'use second'
  end

  proj = projection([[xs[0], ys[0]], [xs[1], ys[1]]], [300,300])
  rotate = Math::atan2(proj[1] - 300, proj[0]- 300) + Math::PI# / Math::PI * 180
  angle-=rotate
  p angle / Math::PI * 180
  p rotate(cx,cy,angle)
  angle = -angle
  
  mp = []
  (150...450).each.with_index do |y,i|
    mp <<= []
    (n - 1).times do |x|
      if img.pixel_color(*rotate((x+1) * 600 / (n + 1) + 300 / (n + 1), y,angle)).red <= 127*257
        next if mp.size >= 2 && (
          mp[-2].include?([x+1,x+2]) || mp[-3].include?([x+1,x+2]) || mp[-4].include?([x+1,x+2])
        )
        mp[-1] << [x+1,x+2]
      end
    end
  end
  mp.delete_if {|a| a == [] }
  target = [*0...n].find{|i| img.pixel_color(*rotate( 600 * ( i + 1 ) / (n + 1), 470,angle)).red <= 10*257 }
  p mp
  current = target + 1
  mp.reverse.each do |arr|
    p current
    arr.each do |x,y|
      if x == current
        current = y
      elsif y == current
        current = x
      end
    end
  end
  s.puts current
  s.puts
end

def stage1(s, base64)
  common_stage(s, base64, 5, 100)
end

def stage2(s, base64)
  common_stage(s, base64, 6, 86)
end

def stage3(s, base64)
  common_stage(s, base64, 7, 75)
end

def stage4(s, base64)
  common_stage(s, base64, 8, 66)
end

def stage5(s, base64)
  common_stage2(s, base64, 4)
end

def stage6(s, base64)
  common_stage2(s, base64, 5)
end

def stage7(s, base64)
  common_stage2(s, base64, 6)
end

def stage8(s, base64)
  common_stage2(s, base64, 7)
end


def stage9(s, base64)
  common_stage2(s, base64, 8)
end

def stage10(s, base64)
  File.binwrite('/tmp/tmp.png', Base64.decode64(base64))
  common_stage3(s, '/tmp/tmp.png', 4)
end

def stage11(s, base64)
  File.binwrite('/tmp/tmp.png', Base64.decode64(base64))
  common_stage3(s, '/tmp/tmp.png', 5)
end

def stage12(s, base64)
  File.binwrite('/tmp/tmp.png', Base64.decode64(base64))
  common_stage3(s, '/tmp/tmp.png', 6)
end

def stage13(s, base64)
  File.binwrite('/tmp/tmp.png', Base64.decode64(base64))
  common_stage3(s, '/tmp/tmp.png', 7)
end

def stage14(s, base64)
  File.binwrite('/tmp/tmp.png', Base64.decode64(base64))
  common_stage3(s, '/tmp/tmp.png', 8)
end

def stage15(s, base64)
  File.binwrite('/tmp/tmp.png', Base64.decode64(base64))
  common_stage3(s, '/tmp/tmp.png', 4)
end

def stage16(s, base64)
  File.binwrite('/tmp/tmp.png', Base64.decode64(base64))
  common_stage3(s, '/tmp/tmp.png', 5)
end

def stage17(s, base64)
  File.binwrite('/tmp/tmp.png', Base64.decode64(base64))
  common_stage3(s, '/tmp/tmp.png', 6)
end

def stage18(s, base64)
  File.binwrite('/tmp/tmp.png', Base64.decode64(base64))
  common_stage3(s, '/tmp/tmp.png', 7)
end

def stage19(s, base64)
  File.binwrite('/tmp/tmp.png', Base64.decode64(base64))
  common_stage3(s, '/tmp/tmp.png', 8)
end
def stage20(s, base64)
  File.binwrite('/tmp/tmp.png', Base64.decode64(base64))
  common_stage3(s, '/tmp/tmp.png', 4)
end

def solve(sock, stage, base64)
  case stage
  when 1
    stage1(sock, base64)
  when 2
    stage2(sock, base64)
  when 3
    stage3(sock, base64)
  when 4
    stage4(sock, base64)
  when 5
    stage5(sock, base64)
  when 6
    stage6(sock, base64)
  when 7
    stage7(sock, base64)
  when 8
    stage8(sock, base64)
  when 9
    stage9(sock, base64)
  when 10
    stage10(sock, base64)
  when 11
    stage11(sock, base64)
  when 12
    stage12(sock, base64)
  when 13
    stage13(sock, base64)
  when 14
    stage14(sock, base64)
  when 15
    stage15(sock, base64)
  when 16
    stage16(sock, base64)
  when 17
    stage17(sock, base64)
  when 18
    stage18(sock, base64)
  when 19
    stage19(sock, base64)
  when 20
    stage20(sock, base64)
  end
end

TCPSocket.open('203.178.132.117', '42719') do |s|
  s.echo = true
  s.echo_color= false
  stage = 0
  # 最初のメッセージ
  7.times{ s.gets }
  while $_ = s.gets
    if /^Stage #(\d+)/ =~ $_
      stage = $1.to_i
    elsif /^#(\d+)/ =~ $_
      p $1
      puts "Stage #{stage}: #{$1}"
      base64 = s.gets
      s.gets # Answer?
      solve(s,stage, base64)
    end
  end
end
}}}

amida (misc 400)

黒丸を高さ470の所になるまで回転させ、位置を補正して、あみだくじをパースした。

本番中はフラグ2まで、終了後同じプログラムでフラグ3を、数行改変することでフラグ4を得ることが出来た。

   1 require_relative 'ctf'
   2 require 'RMagick'
   3 require 'base64'
   4 include Magick
   5 
   6 def common_stage(s, base64, n, w) 
   7   File.binwrite('/tmp/tmp.png', Base64.decode64(base64))
   8   img = ImageList.new('/tmp/tmp.png')
   9   mp = []
  10   (150...450).step(2).each.with_index do |y,i|
  11     mp <<= []
  12     (n - 1).times do |x|
  13       if img.pixel_color((x+1) * w + w / 2, y).red == 0
  14         mp[-1] << [x+1,x+2]
  15       end
  16     end
  17   end
  18   mp.delete_if {|a| a == [] }
  19   target = [*0...n].find{|i| img.pixel_color( ( i + 1 ) * w, 470).red == 0 }
  20   current = target + 1
  21   mp.reverse.each do |arr|
  22     arr.each do |x,y|
  23       if x == current
  24         current = y
  25       elsif y == current
  26         current = x
  27       end
  28     end
  29   end
  30   s.puts current
  31   s.puts
  32 end
  33 
  34 def common_stage2(s, base64, n) 
  35   File.binwrite('/tmp/tmp.png', Base64.decode64(base64))
  36   img = ImageList.new('/tmp/tmp.png')
  37   mp = []
  38   (150...450).each.with_index do |y,i|
  39     mp <<= []
  40     (n - 1).times do |x|
  41       if img.pixel_color((x+1) * 600 / (n + 1) + 1, y).red <= 3*257
  42         next if mp.size >= 2 && mp[-2].include?([x+1,x+2])
  43         mp[-1] << [x+1,x+2]
  44       end
  45     end
  46   end
  47   mp.delete_if {|a| a == [] }
  48   target = [*0...n].find{|i| img.pixel_color( 600 * ( i + 1 ) / (n + 1), 470).red == 0 }
  49   p mp
  50   current = target + 1
  51   mp.reverse.each do |arr|
  52     p current
  53     arr.each do |x,y|
  54       if x == current
  55         current = y
  56       elsif y == current
  57         current = x
  58       end
  59     end
  60   end
  61   s.puts current
  62   s.puts
  63 end
  64 
  65 require 'matrix'
  66 def common_stage3(s, filename, n) 
  67   def rotate(x,y,angle)
  68     y = 600 - y
  69     angle = -angle
  70     x,y = x - 300, y - 300
  71     nx = x * Math::cos(angle) - y * Math::sin(angle)
  72     ny = x * Math::sin(angle) + y * Math::cos(angle)
  73     return nx + 300, 600 - (ny + 300)
  74   end
  75   def dot(x1,y1,x2,y2)
  76     x1.to_f*x2.to_f+y1.to_f*y2.to_f
  77   end
  78   def norm(x,y)
  79     x * x.to_f + y * y.to_f
  80   end
  81   def projection(l, p)
  82     p l
  83     t = dot(p[0]-l[0][0],p[1]-l[0][1],l[1][0] - l[0][0], l[1][1] - l[0][1]) / norm(l[0][0] - l[1][0], l[0][1] - l[1][1])
  84     [l[0][0] + (l[1][0] - l[0][0]) * t, l[0][1] + (l[1][1] - l[0][1]) * t]
  85   end
  86   img = ImageList.new(filename)
  87   cx,cy=nil,nil
  88   img.rows.times do |y|
  89     break if cx
  90     img.columns.times do |x|
  91       next unless img.pixel_color(x,y).red == 0
  92       ok = true
  93       (-1..1).each do |dx|
  94         (-1..1).each do |dy|
  95           ok = false if img.pixel_color(x + dx * 5, y + dy * 5).red != 0
  96         end
  97       end
  98       if ok
  99         # found
 100         cx, cy = x,y
 101         break
 102       end
 103     end
 104   end
 105   p ["Circle:", cx, cy]
 106   r = Math::sqrt((300 - cx) ** 2 + (300 - cy) ** 2)
 107   angle = Math::atan2(-cy + 300, cx - 300) + Math::PI / 2
 108   angle2=nil
 109   if r >= 170
 110   angle2 = Math::atan2(Math::sqrt(r*r-170*170),170)
 111   else
 112     angle2 = 0
 113   end
 114   p angle / Math::PI * 180
 115   p angle / Math::PI * 180
 116   p rotate(cx,cy,angle)
 117   p 'rotate2'
 118   p (angle + angle2) / Math::PI * 180
 119   p rotate(cx,cy,angle + angle2)
 120   angle += angle2
 121   ys = [200, 250]
 122   xs = ys.map{|y| 
 123     img.columns.times.to_a.index do |x|
 124       img.pixel_color(*rotate(x,y,-angle)).red <= 127 * 257
 125     end
 126   }
 127   p xs
 128   dsum = if !xs[1] || !xs[0]
 129            9999999
 130          else
 131            wt = 600 / (n + 1)
 132            (xs[0] - wt).abs + (xs[1] - wt).abs
 133          end
 134   p 'next try'
 135   p (angle) / Math::PI * 180
 136   fxs = xs + []
 137   angle -= angle2 * 2
 138   xs = ys.map{|y| 
 139     img.columns.times.to_a.index do |x|
 140       img.pixel_color(*rotate(x,y,-angle)).red <= 127 * 257
 141     end
 142   }
 143   p xs
 144   qsum = if !xs[1] || !xs[0]
 145            9999999
 146          else
 147            wt = 600 / (n + 1)
 148            (xs[0] - wt).abs + (xs[1] - wt).abs
 149          end
 150   p ['first', dsum]
 151   p ['first', qsum]
 152   if dsum < qsum
 153     p 'use first'
 154     xs = fxs
 155     angle += angle2 * 2
 156   else
 157     p 'use second'
 158   end
 159 
 160   proj = projection([[xs[0], ys[0]], [xs[1], ys[1]]], [300,300])
 161   rotate = Math::atan2(proj[1] - 300, proj[0]- 300) + Math::PI# / Math::PI * 180
 162   angle-=rotate
 163   p angle / Math::PI * 180
 164   p rotate(cx,cy,angle)
 165   angle = -angle
 166   
 167   mp = []
 168   (150...450).each.with_index do |y,i|
 169     mp <<= []
 170     (n - 1).times do |x|
 171       if img.pixel_color(*rotate((x+1) * 600 / (n + 1) + 300 / (n + 1), y,angle)).red <= 127*257
 172         next if mp.size >= 2 && (
 173           mp[-2].include?([x+1,x+2]) || mp[-3].include?([x+1,x+2]) || mp[-4].include?([x+1,x+2])
 174         )
 175         mp[-1] << [x+1,x+2]
 176       end
 177     end
 178   end
 179   mp.delete_if {|a| a == [] }
 180   target = [*0...n].find{|i| img.pixel_color(*rotate( 600 * ( i + 1 ) / (n + 1), 470,angle)).red <= 10*257 }
 181   p mp
 182   current = target + 1
 183   mp.reverse.each do |arr|
 184     p current
 185     arr.each do |x,y|
 186       if x == current
 187         current = y
 188       elsif y == current
 189         current = x
 190       end
 191     end
 192   end
 193   s.puts current
 194   s.puts
 195 end
 196 
 197 def stage1(s, base64)
 198   common_stage(s, base64, 5, 100)
 199 end
 200 
 201 def stage2(s, base64)
 202   common_stage(s, base64, 6, 86)
 203 end
 204 
 205 def stage3(s, base64)
 206   common_stage(s, base64, 7, 75)
 207 end
 208 
 209 def stage4(s, base64)
 210   common_stage(s, base64, 8, 66)
 211 end
 212 
 213 def stage5(s, base64)
 214   common_stage2(s, base64, 4)
 215 end
 216 
 217 def stage6(s, base64)
 218   common_stage2(s, base64, 5)
 219 end
 220 
 221 def stage7(s, base64)
 222   common_stage2(s, base64, 6)
 223 end
 224 
 225 def stage8(s, base64)
 226   common_stage2(s, base64, 7)
 227 end
 228 
 229 
 230 def stage9(s, base64)
 231   common_stage2(s, base64, 8)
 232 end
 233 
 234 def stage10(s, base64)
 235   File.binwrite('/tmp/tmp.png', Base64.decode64(base64))
 236   common_stage3(s, '/tmp/tmp.png', 4)
 237 end
 238 
 239 def stage11(s, base64)
 240   File.binwrite('/tmp/tmp.png', Base64.decode64(base64))
 241   common_stage3(s, '/tmp/tmp.png', 5)
 242 end
 243 
 244 def stage12(s, base64)
 245   File.binwrite('/tmp/tmp.png', Base64.decode64(base64))
 246   common_stage3(s, '/tmp/tmp.png', 6)
 247 end
 248 
 249 def stage13(s, base64)
 250   File.binwrite('/tmp/tmp.png', Base64.decode64(base64))
 251   common_stage3(s, '/tmp/tmp.png', 7)
 252 end
 253 
 254 def stage14(s, base64)
 255   File.binwrite('/tmp/tmp.png', Base64.decode64(base64))
 256   common_stage3(s, '/tmp/tmp.png', 8)
 257 end
 258 
 259 def stage15(s, base64)
 260   File.binwrite('/tmp/tmp.png', Base64.decode64(base64))
 261   common_stage3(s, '/tmp/tmp.png', 4)
 262 end
 263 
 264 def stage16(s, base64)
 265   File.binwrite('/tmp/tmp.png', Base64.decode64(base64))
 266   common_stage3(s, '/tmp/tmp.png', 5)
 267 end
 268 
 269 def stage17(s, base64)
 270   File.binwrite('/tmp/tmp.png', Base64.decode64(base64))
 271   common_stage3(s, '/tmp/tmp.png', 6)
 272 end
 273 
 274 def stage18(s, base64)
 275   File.binwrite('/tmp/tmp.png', Base64.decode64(base64))
 276   common_stage3(s, '/tmp/tmp.png', 7)
 277 end
 278 
 279 def stage19(s, base64)
 280   File.binwrite('/tmp/tmp.png', Base64.decode64(base64))
 281   common_stage3(s, '/tmp/tmp.png', 8)
 282 end
 283 def stage20(s, base64)
 284   File.binwrite('/tmp/tmp.png', Base64.decode64(base64))
 285   common_stage3(s, '/tmp/tmp.png', 4)
 286 end
 287 
 288 def solve(sock, stage, base64)
 289   case stage
 290   when 1
 291     stage1(sock, base64)
 292   when 2
 293     stage2(sock, base64)
 294   when 3
 295     stage3(sock, base64)
 296   when 4
 297     stage4(sock, base64)
 298   when 5
 299     stage5(sock, base64)
 300   when 6
 301     stage6(sock, base64)
 302   when 7
 303     stage7(sock, base64)
 304   when 8
 305     stage8(sock, base64)
 306   when 9
 307     stage9(sock, base64)
 308   when 10
 309     stage10(sock, base64)
 310   when 11
 311     stage11(sock, base64)
 312   when 12
 313     stage12(sock, base64)
 314   when 13
 315     stage13(sock, base64)
 316   when 14
 317     stage14(sock, base64)
 318   when 15
 319     stage15(sock, base64)
 320   when 16
 321     stage16(sock, base64)
 322   when 17
 323     stage17(sock, base64)
 324   when 18
 325     stage18(sock, base64)
 326   when 19
 327     stage19(sock, base64)
 328   when 20
 329     stage20(sock, base64)
 330   end
 331 end
 332 
 333 TCPSocket.open('203.178.132.117', '42719') do |s|
 334   s.echo = true
 335   s.echo_color=  false
 336   stage = 0
 337   # 最初のメッセージ
 338   7.times{ s.gets }
 339   while $_ = s.gets
 340     if /^Stage #(\d+)/ =~ $_
 341       stage = $1.to_i
 342     elsif /^#(\d+)/ =~ $_
 343       p $1
 344       puts "Stage #{stage}: #{$1}"
 345       base64 = s.gets
 346       s.gets # Answer?
 347       solve(s,stage, base64)
 348     end
 349   end
 350 end

CTF/Writeup/tkbctf4/amida (最終更新日時 2014-11-04 18:32:34 更新者 nomeaning)