Login
Immutable PageDiscussionInfoAttachments
CTF/Writeup/31C3 CTF/otp

MMA

otp

   1 require 'metasm'
   2 
   3 process = Metasm::OS.current.create_process('./otp.bin -g token65.bin')
   4 debugger = process.debugger
   5 debugger.bpx(0x40613a, false) do 
   6   puts "SHA256_hash:"
   7   addr = debugger[:rdi]
   8   size = debugger[:rsi]
   9   @addr2 = debugger[:rdx]
  10   p ['%x'%addr,size]
  11   p debugger[addr,size].unpack("H*")
  12 end
  13 debugger.bpx(0x4061ae, false) do
  14   puts "result: %s" % debugger[@addr2,32].unpack("H*")
  15 end
  16 debugger.run_forever

16文字: ユーザー名+secretの上位7byteをそれぞれ1byte毎にsha256sumしてxorしたもの
16文字: sequenceを16進数表記にしたもの
32文字: sequence + secretのsha256sumの先頭32文字

   1 require 'digest/sha2'
   2 require 'facets'
   3 def gen(user, secret, seq) 
   4   s = "\0" * (user.size + 8)
   5   d = "\0" * 8
   6   user.chars.each.with_index do |c,i|
   7     s[i] = c
   8     digest = Digest::SHA256.digest(s)
   9     d ^= digest
  10     s[i] = "\0"
  11   end
  12   8.times do |i|
  13     next if i == 0
  14     s[user.size + i] = if i == 0
  15                          0.chr
  16                        else
  17                          ((secret >> (i*8)) & 255).chr
  18                        end
  19     digest = Digest::SHA256.digest(s)
  20     d ^= digest
  21     s[user.size + i] = "\0"
  22   end
  23   f_hash = d.unpack("H*")[0]
  24 
  25   sequence = [seq].pack("q").unpack("H*")[0]
  26   
  27   s_hash = Digest::SHA256.hexdigest([seq].pack("q") + [secret].pack("q"))
  28 
  29   f_hash + sequence + s_hash[0,32]
  30 end
  31 
  32 p gen('nomeaning',2459565876494672537,37)

   1 require 'digest/sha2'
   2 require 'facets'
   3 target = ["9ae684ca583214d3"].pack("H*") # 目的とするHash
   4 "admin".chars.each.with_index do |c,i| # ユーザー名によるHashを打ち消す
   5   s = "\0" * 13
   6   s[i] = c
   7   target ^= Digest::SHA256.digest(s)
   8 end
   9 
  10 # 1792 vars equation
  11 matrix = Array.new(128){Array.new(1793)}
  12 (0...7).each do |pos|
  13   (0...256).each do |char|
  14     s = "\0" * 13
  15     s[pos + 6] = char.chr
  16     digest = Digest::SHA256.digest(s)[0,8]
  17     # 256bit
  18     print '%d' % digest.unpack("H*")[0].to_i(16)
  19     print ' '
  20   end
  21   puts 
  22 end
  23 
  24 puts target.unpack("H*")[0].to_i(16)

   1 #include <bitset>
   2 #include <algorithm>
   3 #include <iostream>
   4 #include <vector>
   5 #include <cstdint>
   6 using namespace std;
   7 unsigned long long a[7][256], target;
   8 unsigned long long list[256*256*256];
   9 unsigned long long result;
  10 int sel[7];
  11 int from, to;
  12 int search(int pos, unsigned long long cur) {
  13   if(pos == 7) {
  14     if(binary_search(list, list+256*256*256, cur)) {
  15       cout << "-----" << endl;
  16       cout << cur << endl;
  17       for(int i = 0; i < 7; i++) {
  18         cout << sel[i] << endl;
  19       }
  20       result =  cur;
  21       cout << "-----" << endl;
  22     }
  23     return 1;
  24   }
  25   for(int i = 0; i < 256; i++) {
  26     if(pos == 3 && !(from <= i && i < to))continue;
  27     sel[pos] = i;
  28     search(pos + 1, cur ^ a[pos][i]);
  29     if(pos == 3) cout << "search:" << i << endl;
  30   }
  31   return 1;
  32 }
  33 
  34 int main(int argc, char **argv) {
  35   from = atoi(argv[1]);
  36   to = atoi(argv[2]);
  37   cerr << from << "," << to << endl;
  38   for(int i = 0; i < 7; i++) {
  39     for(int j = 0; j < 256; j++) {
  40       cin >> a[i][j];
  41     }
  42   }
  43   cin >> target;
  44   // 3つを選択する
  45   for(int i = 0; i < 256; i++) {
  46     for(int j = 0; j < 256; j++) {
  47       for(int k = 0; k < 256; k++) {
  48         list[i*256*256+j*256+k] = a[0][i] ^ a[1][j] ^ a[2][k];
  49       }
  50     }
  51   }
  52   sort(list, list+256*256*256);
  53   search(3, target);
  54   for(int i = 0; i < 256; i++) {
  55     for(int j = 0; j < 256; j++) {
  56       for(int k = 0; k < 256; k++) {
  57         if(result == (a[0][i] ^ a[1][j] ^ a[2][k])) {
  58           cout << i << endl << j << endl << k << endl;
  59         }
  60       }
  61     }
  62   }
  63 }

$ ruby solve.rb | ./search 0 256
...
-----
9807512490306708300
0
0
0
140
153
187
73
-----
search:140
...
193
14
67

   1 secret = [193,14,67,140,153,187,73].reverse.pack("C*").unpack("H*")[0].to_i(16)*256
   2 while true
   3   break if gen('admin',secret,1337) == '9ae684ca583214d33905000000000000fd635dded0bbb40e162da79fba55ae32'
   4   secret += 1
   5 end
   6 puts gen('admin', secret, 1338)

$ ruby gen.rb
9ae684ca583214d33a0500000000000030949b105cb796db1a0488099b684373

このOTPでログインしたところ、フラグ31C3_a7e3683344e954efd8a58a2a3da7fbe8が得られた。

CTF/Writeup/31C3 CTF/otp (last edited 2014-12-30 14:15:11 by nomeaning)