Login
Immutable PageDiscussionInfoAttachments
CTF/Writeup/tkbctf4/amida

MMA

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 (last edited 2014-11-04 18:32:34 by nomeaning)