Skip to content

Instantly share code, notes, and snippets.

@shinh
Last active May 5, 2021 04:45
Show Gist options
  • Save shinh/242786e2f6a38f9f50803e64a1882715 to your computer and use it in GitHub Desktop.
Save shinh/242786e2f6a38f9f50803e64a1882715 to your computer and use it in GitHub Desktop.
DEF CON CTF 2021 Qual back-to-qoo
#!/usr/bin/env ruby
# qoo_run.rb の結果を ruby qoo.rb log として食べさせると secret を出すやつ
c1s = []
c2s = []
p1s = []
wins = []
msgs = []
no_changes = []
File.readlines(ARGV[0] || 'qoo2.log').each do |line|
if line =~ /Your competitor bets on (\d+)/
c1s << $1.to_i
end
if line =~ /zardus's competitor bets on (\d+), you bet on (\d+)/
c2s << $1.to_i
p1s << $2.to_i
end
if line =~ /\[-\] OK/
no_changes << 1
end
if line =~ /\[-\] ZZZ/
no_changes << 0
end
if line =~ /Win|Lose/
wins << (($& == "Win") ? 1 : 0)
end
if line =~ /zardus receives from adamd: \d+:(\d)/
msgs << $1.to_i
end
end
p [c1s.size, c2s.size, wins.size, msgs.size, p1s.size, no_changes.size]
# p c1s
# p c2s
# p p1s
# p wins
# p msgs
key_str = ''
t = 0
c1s.zip(c2s, p1s, wins, msgs, no_changes).each do |c1, c2, p1, win, msg, nc|
if c2 == 1
measure = "H|Q>"
else
measure = "|Q>"
end
#p2 = (c1*c2) ^ p1
if win == 1
p2 = (c1*c2) ^ p1
else
p2 = (c1*c2) ^ p1 ^ 1
end
sec = c2 == msg ? 1 : 0
puts "turn=#{t} m=#{measure} c1=#{c1} c2=#{c2} c1*c2=#{c1*c2} p1=#{p1} p2=#{p2} sec=#{sec} nc=#{nc} win=#{win} chk=#{(p1^p2)==(c1*c2)}"
if sec == 1
# if c2 == 1
# key_str += '?'
# else
# key_str += p2.to_s
# end
# rotate してない & base が 0 だったら信用できて、残り 32bit くらい総当たり、という問題だと思ってた
#if nc == 1 && msg == 0
#if nc == 1 && c2 == 0
# ……が、なんか rotate した後の measure も信用できて、フラグは取れたけどよくわからん
if nc == 1 || true
key_str += p2.to_s
else
key_str += '?'
end
end
t += 1
end
puts "#{key_str.count("?")} / #{key_str.size}"
puts key_str
p key_str.each_char.map{|c|
c == '?' ? 2 : c.to_i
}.to_a
#num = 0
#refs.zip(msgs).each do |r, m|
# if r == m
# #puts "hm"
# num += 1
# end
#end
#p num
# まあおおむね勝てるやつ
require_relative 'ctfutils'
serv = ARGV[0] || "back-to-qoo.challenges.ooo"
pipe = popen("nc #{serv} 5000")
bets = []
num_wins = 0
128.times do |t|
m = pipe.wait_until(/competitor bets on /)
bet = pipe.get.to_i
STDERR.puts "[-] bet=#{bet}"
bets << bet
# このへん調節して勝率落として rotate の頻度を落とそうとしていました
#if num_wins + (128 - t) * 0.75 > 108 && bet == 0
#if bet == 0
if false
STDERR.puts "[-] OK 0"
#pipe.puts "0"
pipe.puts "2"
pipe.puts "0"
else
STDERR.puts "[-] ZZZ #{num_wins}/#{t+1}"
pipe.puts "2"
pipe.puts bet + 1
#pipe.puts 2 - bet
end
m = pipe.wait_until(/(Win|Lose)/)
if m[0] =~ /Win/
num_wins += 1
end
end
STDERR.puts "[-] #{num_wins}"
pipe.puts ""
pipe.puts ""
pipe.puts ""
pipe.interactive
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment