ログイン
編集不可のページディスカッション情報添付ファイル

2014-11-04 18:31:13時点のリビジョン2

メッセージを消す
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 
 289 
 290 
 291 def solve(sock, stage, base64)
 292   case stage
 293   when 1
 294     stage1(sock, base64)
 295   when 2
 296     stage2(sock, base64)
 297   when 3
 298     stage3(sock, base64)
 299   when 4
 300     stage4(sock, base64)
 301   when 5
 302     stage5(sock, base64)
 303   when 6
 304     stage6(sock, base64)
 305   when 7
 306     stage7(sock, base64)
 307   when 8
 308     stage8(sock, base64)
 309   when 9
 310     stage9(sock, base64)
 311   when 10
 312     stage10(sock, base64)
 313   when 11
 314     stage11(sock, base64)
 315   when 12
 316     stage12(sock, base64)
 317   when 13
 318     stage13(sock, base64)
 319   when 14
 320     stage14(sock, base64)
 321   when 15
 322     stage15(sock, base64)
 323   when 16
 324     stage16(sock, base64)
 325   when 17
 326     stage17(sock, base64)
 327   when 18
 328     stage18(sock, base64)
 329   when 19
 330     stage19(sock, base64)
 331   when 20
 332     stage20(sock, base64)
 333   end
 334 end
 335 
 336 TCPSocket.open('203.178.132.117', '42719') do |s|
 337   s.echo = true
 338   s.echo_color=  false
 339   stage = 0
 340   # 最初のメッセージ
 341   7.times{ s.gets }
 342   while $_ = s.gets
 343     if /^Stage #(\d+)/ =~ $_
 344       stage = $1.to_i
 345     elsif /^#(\d+)/ =~ $_
 346       p $1
 347       puts "Stage #{stage}: #{$1}"
 348       base64 = s.gets
 349       s.gets # Answer?
 350       solve(s,stage, base64)
 351     end
 352   end
 353 end

}